ResourceBundleMessagesource - No way to access all properties from a file? - java

Came across this issue, while implementing i18n using spring resource bundle, for a spring based java project, which has a html+js UI.
I need to read all content from a properties file, for a particular locale, and pass this info to the client side, so that the relevant messages can be shown on the UI.
However, the ResourceBundleMessagesource/ReloadableResourceBundleMessagesource objects seem to allow retrieving only a single message at a time.
ReloadableResourceBundleMessageSource msgSource = new ReloadableResourceBundleMessageSource();
//Methods to get only a single message at a time
String message = msgSource.getMessage("edit.delete.success", null, new Locale(localeString));
I am currently using java.util.ResourceBundle, and looping over the object using it's keyset.
rB = ResourceBundle.getBundle("messages", new Locale(localeString));
Map<String, String> msgs = new HashMap<>();
for(String messageKey : rB.keySet()){
msgs.put(messageKey, rB.getString(messageKey));
}
Q1 : Is there any better/more elegant way to solve this?
Q2 : What is the reason for the authors to not allow for accessing all properties from a file ?

Related

Kafka Client get retention.bytes programmatically

Using Kafka Admin from Java I'm trying to find how can I get the retention.bytes and retention.ms from a topic
The only thing I found in the API is this
adminClient.describeConfigs(Collection<ConfigRsources>???).values().get(ConfigResource???).get().get(String).
In case this is the way, not sure where I can get where it supposed to be passed.
The last string I guess it would be the config name retention.byte
where I can get
Read through the Javadoc. ConfigResource has a Type enum.
Then describing accepts a collection and returns a map via values, keyed by items in that collection. Therefore, pull out the reference to its own variable for reuse.
Then I suggest using constants
rather than strings.
Map<String, Object> config = new HashMap<>();
config.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG,"localhost:9092");
AdminClient client = AdminClient.create(config);
ConfigResource resource = new ConfigResource(ConfigResource.Type.TOPIC, "example");
Config topicConfig = client.describeConfigs(Collections.singletonList(resource)).values().get(resource);
topicConfig.get(TopicConfig.RETENTION_BYTES_CONFIG);
topicConfig.get(TopicConfig.RETENTION_MS_CONFIG);

Freemarker - generate xml from flt template and java methods

I am fairly new to Freemarker and to template engine in general.
Basicly I want to be able to generate two XML files (from two different templates) using java methods to feed data to the template.
For example:
myTemplate1.ftl contain an opening and closing "res" tag with getRes() method as value (return 1 for exemple)
myTemplate2.ftl contain an opening and closing "result" tag and takes getResult() method as value (return 2 for exemple)
How can I write one class Main to process this without being specific (I do not want to write line per line, because then it would be pointless to create an engine)
Can you please help me understand how it work through an example if possible ?
Regards
EDIT with all the new informations :
#fustaki This is very frustrating. It seems I need to go step by step to understand what I'm doing. So... Here is a very dumb example of where I am :
template1.ftl
<Email>${item.getEmail()}</Email><Language>${item.getLanguage()}</Language>
FillMyTemplate1.java
public String getEmail(){ return "test#test.com" }
public String getLanguage(){ return "EN" }
I am using a property file in order to use introspection : prop.properties which contain :
template1=fr.freemarker.test.xml.FillMyTemplate1
MainTest.java
public static void main(String[] args) throws Exception {
Properties prop = new Properties();
InputStream input = new FileInputStream("prop.properties");
prop.load(input);
Class<?> classe = Class.forName(prop.getProperty(args[0])); //where args[0] is "template1"
Configuration config=new Configuration();
config.setClassForTemplateLoading(MainTest.class, "templates");
config.setObjectWrapper(new DefaultObjectWrapper());
Template template=config.getTemplate(args[0]+".ftl");
Map<String, Object> dataModel = new HashMap<String, Object>();
Writer consoleWriter = new OutputStreamWriter(System.out);
dataModel.put("item", classe.newInstance());
template.process(dataModel, consoleWriter);
}
And the result : <Email>test#test.com</Email><Language>EN</Language>
In order to understand what you said, I need to know how a "data-provider" would look like in my case ? How can I get ride of this "item" in my map ? I understand the principle but not the technical solution...
Your Main process is in charge of producing the data (List, Map or other structured object) and templates will use the data to render your XMLs.
The tags used in the templates are independent from the data inside them.
Example where data are stored in a List that can be retrieved with a getItems() or in general is accessible from the freemarker engine.
<?xml>
<res>
<#list items as item >
<item>${item}</item>
</#list>
</res>
You can create as much templates (views) as you want using the same List items.
I hope this clarify your troubles.
here is good example of freemarker. this application generate spring mvc crud operation
using a freemarker template.
springmvcfreemarker

Apache camel simple http example

I am pretty new with Camel. I have been trying to fetch a data from http source.
Here's my code:
from("timer://runOnce?repeatCount=1")
.to("http4://webservice.com/example.xml")
.process(new structureXML())
.to("mock:resource")
.stop();
And:
class structureXML implements Processor {
public void process(Exchange httpExchange) throws Exception {
String httpres = httpExchange.getIn().getBody(String.class);
String[] lines = httpres.split("\n");
Pattern p = Pattern.compile("<Map Key='(.+)' Value='(.+)'/>");
HashMap<String, Integer> mapdata = new HashMap<String, Integer>();
for(String line : lines) {
Matcher m = p.matcher(line);
if(m.find())
mapdata.put(m.group(1), Integer.parseInt(m.group(2)));
}
httpExchange.getIn().setBody(mapdata);
}
}
Well the example works right but I want to know about the possible ways to further improve this situation(e.g xml processing using xpath and etc), also I want to know about the ways which I can store the java object inside the message so I can use it in another route(e.g: direct:resource instead of mock)
About java objects:
More information can be found here: http://camel.apache.org/data-format.html
JAXB
XStream
BeanIO
JiBX
XmlBeans
These data formats will be very useful for transforming XML to POJO.
I recomend you to try BeanIO (detailed documentation, many examples, etc).
About Xpath:
it's hard to tell anything specified without web-service response.
Example:
setBody().xpath("/soap:Envelope/soap:Body/s:insertResponse/s:data",
XmlNamespaces.getNamespace()).
About your example:
You usually need to set a lot of properties and header (before http request), so it worked fine. Example:
setProperty(Exchange.CONTENT_TYPE).constant("application/soap+xml").
setProperty(Exchange.CONTENT_ENCODING).constant("gzip").
setProperty(Exchange.CHARSET_NAME).constant("utf-8").
setHeader(Exchange.CONTENT_TYPE).exchangeProperty(Exchange.CONTENT_TYPE).
And I don't see creating the request to web-service. It is easy to do with the help of velocity (http://camel.apache.org/velocity.html), or, maybe, using SOAP date format (http://camel.apache.org/soap.html).
You can use jetty (http://camel.apache.org/jetty.html) instead of http4 (for me it's easier)

How to transform java object to XML with axis 1.4?

We are using axis 1.4 for our WS implementation.
Whenever the WS request fails we would like to add to our logging the XML of the actual request that was sent.
To do that we of course need to be able to transform the request object into its XML representation, same as it will be sent later to the server.
In most cases this is to be able later copy-paste it to some other tool, for debug, so it is important to have exactly same XML string as it would be sent to the server.
Hope that was clear enough.
Thank you.
OK, answering my own question:
To do so for Axis-1.4, according to the example posted by NJSC, need to replace SerializationContextImpl with just a org.apache.axis.encoding.SerializationContext.
qname = removeNamespaces ? new QName(lname) : new QName(qname.getNamespaceURI(), lname);
final AxisServer server = new AxisServer();
final BeanSerializer ser = new BeanSerializer(obj.getClass(), qname, typeDesc);
final SerializationContext ctx = new SerializationContext(outStr, new MessageContext(server));
ctx.setSendDecl(false);
ctx.setDoMultiRefs(false);
ctx.setPretty(prettyPrint);

Deprecated property in Velocity

I have written pretty basic Velocity template which uses #foreach directive. When I run it, I get the following message in the log:
[warn] The directive.foreach.iterator.name property has been
deprecated. It will be removed (along with $velocityHasNext itself )
in Velocity 2.0. Instead, please use $foreach.hasNext to access this
value from now on.
But the problem is that I don't use this property, at least explicitly. I just use #foreach loop in its basic form, exactly as shown in the user guide.
Below is the simple code which yields this log warning. Velocity version is 1.7.
final Properties properties = new Properties();
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init(properties);
StringWriter stringWriter = new StringWriter();
Map<String, Object> velocityVars = new HashMap<>();
List<Date> dates = new ArrayList<>();
dates.add(new Date());
dates.add(new Date());
velocityVars.put("dates", dates);
VelocityContext velocityContext = new VelocityContext(velocityVars);
String template =
"foo\n" +
"#foreach($d in $dates)\n" +
" $d\n" +
"#end \n" +
"bar";
velocityEngine.evaluate(velocityContext, stringWriter, "blah", template);
System.out.println(stringWriter.toString());
So the question is - why is this warning logged and how do I structure my code to prevent it from appearing?
directive.foreach.iterator.name is not something found in code, but in a velocity.properties file. And for backwards compatibility reasons, this deprecated definition is still present in the default configuration.
The warning is displayed during the initialization of the foreach directive itself, so it's not triggered by something you're doing. You can safely ignore this warning, but if you definitely don't want to see it anymore, you could:
Raise the logging level above WARN
Write you own custom properties file, or just add from Java in the Properties object that you're creating, empty values for directive.foreach.counter.name, directive.foreach.iterator.name and directive.foreach.counter.initial.value.
Or, extract org/apache/velocity/runtime/defaults/velocity.properties from the velocity jar in your classpath directory, and remove from it the deprecated settings.

Categories