I have many classes with static final fields which are used as default values or config. What is best approach to create global config file? Should I move these fields to single
Y,es properties file is always preferable for configuration. There are multiple ways to read it, one being apache commons-configuration.
If the properties are environment-dependent, externalize them (outisde the project), and set the path to them (for example with -Dconfig.location=..
). If they don't change depending on the environment, simply put the properties file on the classpath.
See this article of mine about the envioronment-dependent properties.
Then, you can have a static
holder for the Properties
/ Configuration
/ ... object, or, if possible, inject (if using a DI framework) the values wherever they are needed.
Both the approches are fine:
Have a static class with required final
fields.
Have a singelton but save it from multiple threads appropriately.
if possible use enum
over static fields. This way you can group related fields together.
If these are application level values, i'll prefer static
class over singelton.
and, you should decide if these are const values or configuration value that differ from time to time.
It is good to have them on one place. Property file or static class? Property file should be used for e.g. localization. Static class for e.g. String constants.
As for me, the main difference between the approaches is an ability to change values without changing a code.
With static final fields you must recompile sources to use new values. With .properties files you just usually have to restart an application that may be done by system administrator etc.
So it seems to be a matter of whether it should be changeable or not and whether it should be available for someone except a developer. (In some sense it's a questions who is "in charge of" these values: developer or system administrator/user etc.)
The answer depends...
enum
to static final
constants where possible (avoid "stringly typed" code)static final int SECONDS_IN_HOUR = 3600;
)public static final
in the class that has "most ownership" over themMy favorite approach is the follow:
public class MyProperties {
private static final String BUNDLE_NAME = "my.package.MyProperties"; //$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
.getBundle(BUNDLE_NAME);
private MyProperties() {
}
public static long getLong(String key) {
String strValue = getString(key);
long result = -1;
try {
result = Long.parseLong(strValue);
} catch (Exception exc) {
logger.error(exc.getLocalizedMessage());
}
return result;
}
public static int getInteger(String key) {
String strValue = getString(key);
int result = -1;
try {
result = Integer.parseInt(strValue);
} catch (Exception exc) {
logger.error(exc.getLocalizedMessage());
}
return result;
}
public static String getString(String key) {
String returnValue = System.getProperty(key);
if(returnValue != null && returnValue.length() > 0) {
if(logger.isDebugEnabled()) {
logger.debug(key+" assigned by system property");
}
return returnValue;
}
try {
returnValue = RESOURCE_BUNDLE.getString(key);
} catch (MissingResourceException e) {
returnValue = '!' + key + '!';
}
return returnValue;
}
}
This simple class first search the key in the system properties then in the resource bundle. This means you can override the property settings with -Dkey=value command line options.