Apache Commons logo Commons Configuration

File-based Configurations

Often configuration properties are stored in files on the user's hard disk, e.g. in .properties files or as XML documents. Configuration classes that deal with such properties need to provide typical operations like loading or saving files. The files to be processed can be specified in several different flavors like java.io.File objects, relative or absolute path names, or URLs.

To provide a consistent way of dealing with configuration files in Commons Configuration the FileConfiguration interface exists. FileConfiguration defines a standard API for accessing files and is implemented by many configuration implementations, including PropertiesConfiguration and XMLConfiguration.

In the following sections we take a closer look at the methods of the FileConfiguration interface and how they are used.

Specifying the file

The FileConfiguration interface contains several methods for specifying the file to be loaded. The following variants are supported:

  • With the setFile() method the data file can be specified as a java.io.File object.
  • The setURL() takes a java.net.URL as argument; the file will be loaded from this URL.
  • The methods setFileName() and setBasePath() allows to specify the path of the data file. The base path is important if relative paths are to be resolved based on this file.

While a File or a URL uniquely identify a file, the situation is a bit ambiguous when only a base path and a file name are set. These can be arbitrary strings (even full URLs) whose exact meaning must be detected when the file is loaded. For this purpose file-based configurations perform the following checks (in this order):

  • If the combination from base path and file name is a full URL that points to an existing file, this URL will be used to load the file.
  • If the combination from base path and file name is an absolute file name and this file exists, it will be loaded.
  • If the combination from base path and file name is a relative file path that points to an existing file, this file will be loaded.
  • If a file with the specified name exists in the user's home directory, this file will be loaded.
  • Otherwise the file name is interpreted as a resource name, and it is checked whether the data file can be loaded from the classpath.
If all these checks fail, a ConfigurationException will be thrown.

Loading

After the file name has been defined using one of the methods mentioned above, the load() method can be called. This method tries to locate the file and open it. If this fails, a ConfigurationException is thrown.

The FileConfiguration interface defines multiple overloaded load() methods. The one that takes no argument will always operate on the file name that has been set earlier. All other methods allow to specify the source to be loaded. This can be done as java.io.File, java.net.URL, string (containing either an absolute or relative path), input stream, or reader. When using these variants of the load() method be aware of two things:

  1. They do not change the configuration's file name. To do this you have to explicitly call one of the setter methods.
  2. The load() methods do not empty the configuration before new data is loaded. This makes it easy to construct union configurations by simply calling load() multiple times. But if you want to reuse a Configuration object and load a different file, remember to call the clear() method first to ensure that old properties are wiped out.

File-based configurations typically define a set of constructors that correspond to the various setter methods for defining the data file. These constructors will set the file and then invoke the load() method. So creating a file-based configuration object and loading its content can be done in a single step.

Saving

Saving is implemented analogously to loading: There is a no argument save() method that will use the internal file name. Then for each load() method a corresponding save() method exists that will write the data contained in the configuration to different targets.

An example for loading, manipulating, and saving a configuration (based on a PropertiesConfiguration) could look as follows:

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setProperty("colors.background", "#000000");
config.save();

You can also save a copy of the configuration to another file:

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setProperty("colors.background", "#000000");
config.save("usergui.backup.properties);

Automatic Saving

If you want to ensure that every modification of a configuration object is immediately written to disk, you can enable the automatic saving mode. This is done through the setAutoSave() method as shown in the following example:

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setAutoSave(true);
config.setProperty("colors.background", "#000000"); // the configuration is saved after this call

Be careful with this mode when you have many updates on your configuration. This will lead to many I/O operations, too.

Automatic Reloading

A common issue with file-based configurations is to handle the reloading of the data file when it changes. This is especially important if you have long running applications and do not want to restart them when a configuration file was updated. Commons Configuration has the concept of so called reloading strategies that can be associated with a file-based configuration. Such a strategy monitors a configuration file and is able to detect changes. A default reloading strategy is FileChangedReloadingStrategy. It can be set on a file-based configuration as follows:

PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties");
config.setReloadingStrategy(new FileChangedReloadingStrategy());

FileChangedReloadingStrategy works as follows: On every property access the configuration checks its associated reloading strategy. FileChangedReloadingStrategy will then obtain the last modification date of the configuration file and check whether it has changed since the last access. If this is the case, a reload is triggered. To avoid often disk access when multiple properties are queried from the configuration, a refresh delay can be set on the reloading strategy. This is a time in milli seconds with the meaning that the reloading strategy will only once check the file's last modification time in the period specified here.

Managed Reloading

ManagedReloadingStrategy is an alternative to automatic reloading. It allows to hot-reload properties on a running application but only when requested by admin. The refresh() method will force a reload of the configuration source.

A typical use of this feature is to setup ManagedReloadingStrategy as a JMX MBean. The following code sample uses Springframework MBeanExporter to expose the ManagedReloadingStrategy to the JMX console :


<!-- A file based configuration bean -->
<bean id="configuration" class="(...).PropertiesConfiguration">
    <constructor-arg type="java.net.URL" value="file:${user.home}/custom.properties"/>
    <property name="reloadingStrategy" ref="reloadingStrategy"/>
</bean>

<!-- The managed reloading strategy for the configuration bean -->
<bean id="reloadingStrategy" class="...ManagedReloadingStrategy"/>

<!-- The MBeanExporter that exposes reloadingStrategy to the JMX console -->
<bean id="mbeanMetadataExporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="server" ref="mbeanServer"/>
    <property name="beans">
        <map>
            <entry key="myApp:bean=configuration" value-ref="reloadingStrategy"/>
        </map>
    </property>
</bean>

With this configuration, the JMX console will expose the "myApp:bean=configuration" MBean and it's refresh operation.