Programming in Java, what's the better way to create resource files to save the messages of the application in different languages?
If I use a properties file, inside the code everytime that I need refer to a message I have to write something like that:
ResourceBundle.getBundle("test.messages.messageFile").getString("Message1")
Exists another form to use messages and generate a code cleaner? Maybe create a class with static constants that refer to this messages?
you can use ResourceBundle, but declare it and use it as a variable.
ResourceBundle languageBundle=ResourceBundle.getbundle("test.messages.messageFile");
//later in your code you can say
languageBundle.getString("Message1");
it would help if you make this variable public static
This is the standard way. But nothing forces you to not store the bundle in a field:
private ResourceBundle messages = ResourceBundle.getBundle("test.messages.messageFile");
...
String message1 = messages.getString("Message1");
You may also encapsulate it into a Messages class that has the following method:
public String getMessage1() {
return messages.getString("Message1");
}
It's all up to you.
you can try Internationalization made easier.
This is based on annotations and gives type safety for argument substitution.
Related
In my project,we want manage all REST APIs errorcodes in a Enum type,like the following code:
package com.example.util
public enum ErrorType{
SUCCESS("0000", "success")
PARAMS_EMPTY("3001", "params cannot be empty")
}
The problem we encounter is if we put the class into util package,everytime we add a new error type in business spring boot app,we'll need to modify,publish and recompile the app and util project.That would be hard to maintance the util package.Basically,we prefer to maintance a relatively stable utility package.
So we are considering if there is a way that we can generate Enum type dynamiclly,we can comfigure the error information in mysql in advance,then we can load them into enum type in application boot procedure.
I'm not sure is this a good idea to dynamic generate enum type in Java,or if there is a better solution for this problem.
You can't add or remove values from an enum. Enums are complete static enumerations.
If you need to handle variable values you need to work with a standard class.
For example you can have something like the following:
public Error {
public static Error getByName(String name) {
....
}
public static Error getByCode(int code) {
....
}
}
and use it as follow:
Error myError404 = Error.getByCode(404);
Obviously this code gives you a lot of flexibility, but you cannot know in advance if a particular error code exists or not. And you can't use ide facilities related to enums.
Generating an enum would not be so useful I think, since part of the power of enums is that you can use them statically in your code - so then you have to update your code anyway.
How about adding a an exception handler to your util library that can be populated with error codes / description mappings from the database that can then translate errors/exceptions to response codes / error messages for your API? (just guessing you have an api here :-) )
Thanks for your reply,we finally decide to give up this idea.Dynamic generate an enum would not help,indeed it will add more complexity to our project,it's not a common use of enum.
Instead of this,we predefine our main error type likes user_error,system_error and db_error,etc.The specific error information will be processed in the business service.
i was wondering if it's possible to initialize a constant in an interface from a property file using java or using spring messageSource, or such thing is not possible
please advise, thanks.
You can:
public interface Foo {
String a = Properties.getProperty("foo"); // public static final by default
}
However, that means that Properties.getProperty(..) has to be a static method which relies on an already initialized message source (statically again). Depending on the project and the frameworks you use this might not be the best option.
You could initialise a bean via a configuration which includes a final member. Since it's final you can assign to it during construction/initialisation and it then is immutable.
To configure from a property file using Spring, check out the PropertyPlaceholderConfigurer. That will allow you to initialise Spring beans using one or more property files from your classpath, filesystem, remote services etc.
Yes, that's possible:
public static final CONSTANT = System.getProperty("myProperty");
Although it's possible using some static helper method (as was already suggested), I would strongly recommend you not to do so for 2 reasons:
That looks like a pretty bad design. If you need a dynamic value - make it a method in the interface. Or use a static helper directly - you will need one anyway to make it work.
Constants might be inlined at compile time. That shouldn't happen in this particular case - compiler should go with inlining only if it can prove that value won't change between executions, basically if you initialize it with a literal, But there is a tiny chance that it would. Just think how bad will it be - no matter in which environment the progran is running, it picks up some useless value set during compilation, instead of what is configured. (This is rather a theoretical problem, need to say).
by reading a property file like in the example below.
int property1;
String otherProperty;
public void loadProperties(File propFile) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(propFile));
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("Property1=")) {
property1 = Integer.parseInt(line.substring(10));
}
if (line.startsWith("OtherProperty=")) {
otherProperty = line.substring(14);
}
}
}
I have an XML defined which provides a payload path to a serialized XML. I would like to take these parameters and create an object and call a method in a class. What is the best approach to do this in Java?
XML
<RequestObjectType>com.test.model.QueryType</RequestObjectType>
<Class>com.test.api.Query</Class>
<Method>generalQuery</Method>
public void callRequestViaObj(String payloadXML, String payloadType, String api_className, String method){
Class c_payloadType = Class.forName(payloadType);
Class c_apiClass = Class.forName(api_className);
JAXBElement<c_payloadType> elemreq = (JAXBElement<c_payloadType>) JaxbUtils.XMLtoObj( payloadXML, JAXBContext.newInstance(c_payloadType) );
c_payloadType qreq = (c_payloadType) (elemreq.getValue());
//Would like to do something like this...
c_payloadType.newInstance().callMethod(method).with(qreq);
}
have a look at the reflection-api:
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
section "Invoking Methods by Name"
There are many tools that will do this for you. One of them is Castor.
It looks like you just need to tweak the calls that use the reflection API. Try
c_payloadType.newInstance().getMethod(method, qreq.getClass()).invoke(qreq);
This assumes that c_payloadType is an instance of Class<?> and qreq is the argument you want to pass to the method call. I'm not sure if the JAXB code you've written correctly constructs those two objects.
It is a common way to decouple text messages and source code in C/Python/PHP/etc by means of gettext set of utilities. I'm trying to do something similar in my Java project, according to this instruction. Is it the best possible way? Or I should try something different and more advanced?
ps. I would like to avoid complex initialization and ideally my Java code should look like:
[...]
public String howBigIsTheFile(File f) {
String name = f.getAbsolutePath();
long length = f.length();
return _("The file %s is %d bytes long", name, length);
}
Something like gettext-commons maybe?
I assume this question is about stand-alone application (command-line, SWING, etc) and not about server-side application (with multiple users accessing concurrently).
In stand-alone application, the easiest is to create a single static accessor class that would be responsible for loading a single resource bundle and then looking up strings in that resource bundle.
Something like this:
public class ResourceUtil {
private static ResourceBundle rb;
static {
//set the default locale
setLocale(Locale.ENGLISH);
}
public static void setLocale(Locale locale) {
rb = ResourceBundle.getBundle("Resources", locale);
}
public static String tr(String key, Object... args) {
return MessageFormat.format(rb.getString(key), args);
}
}
You can change the active locale with setLocale(Locale) method and access translated strings with tr(String,Object...) method.
Then, you could call it from your class like this:
import static ResourceUtil.tr;
public String howBigIsTheFile(File f) {
String name = f.getAbsolutePath();
long length = f.length();
return tr("The file %s is %d bytes long", name, length);
}
Notice the static import.
Disclaimer: all provided code is on pseudo-code level and is not guaranteed to compile.
Depending on the size of your application, you might find it useful to use IDE string externalization support (e.g. see chapter in Eclipse JDT help, I'm sure other IDEs have some similar features).
You could also use several resource bundles and/or several static classes - it depends on the size of your application and your personal preference. See this question for further debate about this.
In a server-environment using static approach like above would lead into issues as different users would have different locales. Depending on your webapp framework, you would solve this issue differently (e.g. use MessageSource in Spring).
If you think about I18N/L10N, Java has its own mechanism here: the properties file. You can see an example in the internationalization tutorials. It's even simpler than gettext stuff :).
This might be an age old problem and I am sure everyone has their own ways.
Suppose I have some properties defined such as
secret.user.id=user
secret.password=password
website.url=http://stackoverflow.com
Suppose I have 100 different classes and places where I need to use these properties.
Which one is good
(1) I create a Util class that will load all properties and serve them using a key constant
Such as :
Util is a singleton that loads all properties and keeps up on getInstance() call.
Util myUtil = Util.getInstance();
String user = myUtil.getConfigByKey(Constants.SECRET_USER_ID);
String password = myUtil.getConfigByKey(Constants.SECRET_PASSWORD);
..
//getConfigByKey() - inturns invokes properties.get(..)
doSomething(user, password)
So wherever I need these properties, I can do steps above.
(2) I create a meaningful Class to represent these properties; say,
ApplicationConfig and provide getters to get specific properties.
So above code may look like:
ApplicationConfig config = ApplicationConfig.getInstance();
doSomething(config.getSecretUserId(), config.getPassword());
//ApplicationConfig would have instance variables that are initialized during
// getInstance() after loading from properties file.
Note: The properties file as such will have only minor changes in the future.
My personal choice is (2) - let me hear some comments?
Do it the most straightforward way (a class with static values):
package com.domain.packagename
public class Properties {
private static String hostName;
public static getHostName() { return hostName; }
private static int port;
public static int getPort() { return port; }
public static void load() {
//do IO stuff, probably
hostName = ??;
port = ??;
//etc
}
}
I find the first approach to be more verbose than necessary. (Especially if the properties are not expected to change very much.) Also, by using the second approach you can handle casting/type issues when the properties are loaded instead of when they are used.
Your option (2) to keep application specific getters sounds better and clean.
public static final keys from an interface had been a bad design in Java for ages.
I guess my first question is why you want to create an instance of something you're saying is a singleton (you mentioned using code like Util.getInstance()). A singleton only has 1 instance so you shouldn't try to instantiate multiple copies in your code.
If the data is static (like this appears to be) I'd create a singleton and retrieve the values from it.
I don't think there is any significant advantage of one method over the other and I don't think the solution (1) is more secure, just because it provides a property key instead of a java getter for getting passwords.
If I had to chose one though I would take option (2).