In this section some utility classes will be introduced that can be used to make handling of configuration objects easier. These classes already provide solutions for some often occurring problems. We will list these problems in no specific order and show how they can be solved with classes provided by Commons Configuration.
Often it is required to copy the data of one Configuration
object into another one. For this purpose the
AbstractConfiguration
class (which serves as the base class for
most of the configuration implementations shipped with this library)
provides two methods implementing a basic copy operation:
append()
takes the configuration to be copied
as argument and adds all of its properties to the current configuration.copy()
is very similar to append()
. The
difference is that properties that already exist in the target
configuration are replaced by the properties of the source configuration.
These methods work fine if the target configuration is not a hierarchical configuration. If a hierarchical configuration is to be copied into another one, the methods are not able to handle the hierarchical structure; so the resulting configuration will contain all of the properties of the source configuration, but the specific parent-child relations will probably be lost. If a hierarchical configuration needs to be copied, there are the following options:
clone()
method can be used to create a copy of a
hierarchical configuration. This also works for non-hierarchical
configurations. Most of the configuration implementations provided by
Commons Configurations support cloning. The
cloneConfiguration()
method of
ConfigurationUtils
can be used for creating a copy of an
arbitrary Configuration
object. This method checks whether
the passed in configuration implements the Cloneable
interface and, if so, invokes its clone()
method.Hierarchical configurations provide some enhanced features that are not available for "flat" configurations. For instance they support more sophisticated query facilities. Because of that it may be sometimes useful to transform an ordinary configuration into a hierarchical one. The following code fragment shows how this can be done:
// Create a flat configuration PropertiesConfiguration flatConfig = new PropertiesConfiguration(); flatConfig.load(...); HierarchicalConfiguration hc = ConfigurationUtils.convertToHierarchical(flatConfig);
The convertToHierarchical()
method of
ConfigurationUtils
checks whether the passed in object
is already a hierarchical configuration. If this is the case, it is
returned unchanged. Otherwise a new HierarchicalConfiguration
object is created, and the properties of the source configuration are
copied into it.
When working with the JDK the java.util.Properties
class is
typically used for storing configuration data. If Commons
Configuration is to be integrated in such an application, there may
be the requirement of converting from Properties
objects to
Configuration
objects and vice versa. For this purpose an
utility class can be used:
ConfigurationConverter
.
Usage of this class is pretty simple. It provides some static utility
methods that perform different conversions. Below you can see some
examples. In this fragment we assume that we have a method
processConfiguration()
that is called from older parts of an
application that are not aware of the Commons Configuration API.
So they pass in a Properties
object and expect one as
return value. Inside the method a temporary Configuration
object is created and used.
/** * Does some processing of properties. * @param props the source properties * @return the processed properties */ Properties processConfiguration(Properties props) { // Create a configuration for the properties for easy access Configuration config = ConfigurationConverter.getConfiguration(props); // Now use the Configuration API for manipulating the configuration data ... // Return a Properties object with the results return ConfigurationConverter.getProperties(config); }
Please refer to the Javadocs of
ConfigurationConverter
to learn more about the available
conversion methods and their limitations.
Another issue with the integration of Commons Configuration with
native Java applications can be variables: Configuration implementations
are able to detect variables like ${myReference}
or
${sys:java.version}
in the values of their properties and
substitute them by their current values (see the section
Variable
Interpolation for more details). External components probably do not
know how to handle such placeholders when processing configuration files
written by Commons Configuration.
AbstractConfiguration
provides the method
interpolatedConfiguration()
. This method creates a clone of
the current configuration and then performs interpolation on all of its
properties. So the result of this method is a configuration object with
basically the same content as the original configuration, but with all
variables replaced by their actual values (as far as this was possible).
The following code fragment shows how a
PropertiesConfiguration
object can be saved in a way that the
resulting properties file does not contain any variables:
// Load a properties file (which may contain variables) PropertiesConfiguration config = new PropertiesConfiguration("config.properties"); // Perform interpolation on all variables PropertiesConfiguration extConfig = (PropertiesConfiguration) config.interpolatedConfiguration(); // Save the interpolated configuration (no more variables) extConfig.save("external_config.properties");
Section Error listeners
introduces a way of dealing with runtime exceptions that can occur on
accessing configuration properties by registering an event listener. If
you do not want to provide a special error handler, but only need to
propagate the exception that caused the error event, you can make use of
a convenience method of the
ConfigurationUtils
class: enableRuntimeExceptions()
registers a special error listener at the passed in configuration that
will throw a
ConfigurationRuntimeException
exception for each received
error event. The following code fragment shows an example of using this
method:
JNDIConfiguration config = new JNDIConfiguration(); ConfigurationUtils.enableRuntimeExceptions(config); // This may now throw a ConfigurationRuntimeException String value = config.getString("myKey");
enableRuntimeExceptions()
can be called for all
Configuration
implementations that are derived from
EventSource
(which is the case for almost all configuration
classes provided by this library). Of course the affected implementation
must support the mechanism of error events, otherwise the registered
listener will not be triggered. In
Error listeners more
information can be found.