General
Using Java Config
Design of Java Config
Java Config consists of a few classes that provide type-safe access to properties of a property-file. This makes it very easy for an application to be configurable.
An important feature of Java Config is the possibility to check your entire configuration on validity with a single call. Also, Java Config supports a lot of data-types that are common for Java projects.
The easiest way to get started with Java Config is to use the zips provided at the Download page.
You can always find the latest version of Java Config at the download page. Be assured that all new versions of Java Config will always be downwards compatible.
The website you are currently visiting tries to answer most questions. Next to that, the JavaDocs provide more detailed information on the method calls and classes that form Java Config.
If you would more information feel free to send me an e-mail.
For a list of the currently supported data-types see this page .
The requirement for new configuration get-methods is pretty easy: calls on this method should be be consistent. Before you add a new validation to your Config it's worth reading the design document. Having said this, here's a quick example of a new validation:
public class CustomValidationConfig extends Config { public static final String RESOURCE_NAME = "customvalidation.properties"; public CustomValidationConfig(String resourceName) { super(resourceName); } public int getAmountOfLegs() { int value = getInt("amount.of.legs"); if ((value % 2) != 0) { throw new InvalidPropertyException("amount.of.legs", "" + value, "even number"); } return value; } }
The use of InvalidPropertyException
is optional; any exception that is thrown will be recorded. When an Exception is thrown, the validation method knows that the configuration is incorrect and will report this.
No, an instance of a Config class is immutable. However, it is easy to extend
your config class and override on of the methods, this is specifically useful for unit testing. See below for an example.
Sometimes it is desireable to have propertynames (the keys in the property file) share a common layout. For example, you would like to prefix all the property names in your file with the application name, so that this property file can be used in multiple applications without name clashes. You can achieve this by overwriting the getValue(String) method in Config. In the example below you will see that the property "magicnumber" is retrieved from the file. In the next version of that Config, not "magicnumber" is used, but "mycomponent.magicnumber".
public class CustomValidationConfig extends Config { // constructor left out for brevity public int getMagicNumber() { return getInt("magicnumber"); } }
public class CustomValidationConfig extends Config { // constructor left out for brevity /** * Make sure all values are retrieved from keys starting with * "mycomponent.". */ public String getValue(String key) { return super.getValue("mycomponent." + key); } public int getMagicNumber() { return getInt("magicnumber"); } }
The format of a propery that is read by
getDate(key)
must be in the following format:
November 26, 2003 2:09:28 PM
. This is the Java DateFormat that can be retrieved by
the following call:
DateFormat.getDateTimeInstance(DateFormat.LONG,
DateFormat.MEDIUM, Locale.US)
. I choose this date-format because it is available in
every Java implementation.
This Date format can be useful, for example to
determine at runtime when the current executable was
compiled. Use this format in Ant or Maven for the
property-generating for that:
MMMM d, yyyy hh:mm:ss a
.
Example for Maven:
<ant:tstamp> <format property = "timeforversion" pattern = "MMMM d, yyyy hh:mm:ss a" locale = "en" > </ant:tstamp>
Q: On our project we have a lot of existing property files which would require a lot of work to replace. Can we keep on using our current configuration files in Java Config?
A: Yes, certainly. Java Config uses standard Java property files, and thus support the full features of this format such as comments etc.
If you already have an existing property file, you might be interested in a simple utility that can be found in the CVS repository of Java Config (in directory othersrc). That class generates a Java class from an existing property file.
Java Config is written to be as independent of external libraries as possible. However, the requirement when it comes to Java is strict: Java Config works with Java 1.4 only. The implementation uses regular expressions and chained exceptions, which are built-in in Java 1.4, but would have required external libraries for Java 1.3.
It's possible (if you really want to) to check out the sources and work around 1.4 specific features, but you're on your own in this. It would require a lot of effort to keep two different code-bases in sync. Anyway: Java Config is most useful in new projects, and if you are starting a new project you are not going to use Java 1.3 anymore, are you?
Q: Why are the calls to the Config object not static? In my project I could use the following code, and with Java Config I can't!
String hostname = Config.getFtpHostname();
A: The use of static calls strongly reduces the flexibility of a class. For example, it is very common to use the following type of configuration in a project:
public class ToBeConfigured { private String ftpHostname; ToBeConfigured(Config config) { ftpHostname = config.getFtpHostname(); } public void doIt() { // connect to "ftpHostname" } }
Now, in this type of configuration it's much easier to create a unit test. For example if we want to connect to localhost instead:
class TestConfig extends Config { ... public String getFtpHostname() { return "localhost"; } } public void testWithLocalHost() { // start local FTP server here. ToBeConfigured toBeConfigured = new ToBeConfigured(new TestConfig()); toBeConfigured.doIt(); // will now connect to localhost }
With a static Config.getXxx() call this would have been much harder to accomplish. This way of dealing with component-configuration (passing on a Config object in the constructor) is sometimes called Inversion Of Control (IOC).
Yes. The initialization of the Config class takes place in the constructor, after which the contents of the Config class will never change.
A (documented) exception is the use of the constructor that takes Properties as its argument.