About Us Home Contributors License Components Sandbox Configuration Home Overview Simple Howto ConfigurationFactory Howto XML Howto Composite Config Howto Runtime Dependencies Roadmap Javadoc Extensions Avalon Component Project Documentation About Commons Configuration Downloads Project Info Project Reports Development Process General Information Charter Volunteering Contributing Patches Releasing Components Jakarta Community Get Involved Mailing Lists Access CVS Repositories Commons Resources (Unofficial) Wiki Japanese Translation Korean Translation Related Apache Commons DB Commons XML Commons | ### Using a Configuration Factory This section explains how a `ConfigurationFactory` object is setup that provides access to a collection of different configuration sources. It also discusses using Hierarchical and Structured datasets. #### The configuration definition file When a single configuration file is the only source of configuration data it is very simple to load it using a `PropertiesConfiguration` object (this is the class that handles files of this type). But because we think that later other sources will be added (otherwise this example section would be too silly) we will use a `ConfigurationFactory` object to load it. `ConfigurationFactory` allows to combine multiple configuration sources. The properties defined in these sources can then be accessed as if they were defined in a single configuration file. To make use of this we have to create a XML file which tells the factory from which sources the properties are to be collected. The following listing shows the content of this file:
    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <configuration>
      <properties fileName="usergui.properties"/>
    </configuration>
Definition files for `ConfigurationFactory` are normal XML files. The root element must be named `configuration`. It can contain different sub elements that specify the configuration sources to load. The `properties` element is one of these; it is used to include properties files. For this example we store the definition file for `ConfigurationFactory` in the same directory as the properties file and call it `config.xml`. #### Setting up a ConfigurationFactory Now we have to create a `ConfigurationFactory` object and let it read this definition file. This is quite simple: Just create a new instance and set the name of the definition file with the `setConfigurationFileName()` method.
    ConfigurationFactory factory = new ConfigurationFactory();
    URL configURL = new File("config.xml").toURL();
    factory.setConfigurationFileName(configURL.toString());
    Configuration config = factory.getConfiguration();
As this code fragment shows the file name passed to the factory can be a full URL. This is also the recommended way of specifying the file because it provides the greatest flexibility and a consistent way of handling relative file names found in the definition file. Here we assumed the configuration definition file to be located in the current directory. It is also possible (and probably a better approach) to load the file from the class path. This could be done as follows:
    ConfigurationFactory factory = new ConfigurationFactory();
    URL configURL = getClass().getResource("/config.xml");
    factory.setConfigurationURL(configURL);
    Configuration config = factory.getConfiguration();
#### Accessing properties Whatever way we used to load the configuration factory, we should now have a `Configuration` object that was returned by the factory's `getConfiguration()` method. This object defines a large amount of methods for querying properties. The most generic one is `getProperty()`, which returns an object, but there are lots of other methods that return other datatypes. In our example the property we have defined has a string value, so we would use the `getString()` method. All of these methods have in common that they expect a property key as argument. Here the name of the searched property must be provided in exact the same way as it is contained in the properties file. To obtain the value of the background color property that is defined in the properties file shown earlier the following code fragment can be used:
    String backColor = config.getString("color.background");
### Multiple configuration sources Using `ConfigurationFactory` to collect configuration sources does not make much sense if there is only one source to be loaded. So let's add another one! This time we will embedd a XML file. #### A XML configuration file Many applications use the popular XML format for storing configuration information. So it is no wonder that Configuration also supports this type of configuration sources. In general each XML document can be used to define configuration settings. We start here with a rather simple one:
    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <gui-definition>
      <colors>
        <background>#808080</background>
        <text>#000000</text>
        <header>#008000</header>
        <link normal="#000080" visited="#800080"/>
      </colors>
      <rowsPerPage>15</rowsPerPage>
    </gui-definition>
(As becomes obvious, this tutorial does not bother with good design of XML documents, the example file should rather demonstrate the different ways of accessing properties.) This XML document should be stored under the name `gui.xml` in the same directory as the so far created configuration files. #### Overriding properties To make this XML document part of our global configuration we have to modify our configuration definition file to also include the new file. For XML documents the element `xml` can be used so that we have now:
    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <configuration>
      <properties fileName="usergui.properties"/>
      <xml fileName="gui.xml"/>
    </configuration>
The code for setting up the `ConfigurationFactory` object remains the same. The following fragment shows how the new properties can be accessed:
    String backColor = config.getString("color.background");
    String textColor = config.getString("color.text");
    String linkNormal = config.getString("color.link[@normal]");
    int rowsPerPage = config.getInt("rowsPerPage");
This listing demonstrates some important points of constructing keys for accessing properties load from XML documents: Nested elements are accessed using a dot notation. In the example document there is an element `<text>` in the body of the `<color>` element. The corresponding key is `color.text`. The root element is ignored when constructing keys. In the example you do not write `gui-definition.color.text`, but only `color.text`. Attributes of XML elements are accessed in a XPath like notation. There is one problem with the example code fragement: It queries the value of the `color.background` property, but this is defined in both the properties and the XML file and - to make things worse - with different values. Which value will be returned by the corresponding call to `getString()`? The answer is that the configuration sources are searched in the order they are defined in the configuration definition file. Here the properties file is included first, then comes the XML file. Because the `color.background` property can be found in the properties file the value specified there will be returned (which happens to be `#FFFFFF`). It might not be obvious why it makes sense to define the value of one and the same property in multiple configuration sources. But consider the following scenario: An application comes with a set of default properties and allows the user to override some or all of them. This can now easy be realized by saving the user's settings in a file and the default settings in another. Then in the configuration definition file the file with the user settings is included first and after that the file with the default values. The application code that queries these settings need not be aware whether a property was overriden by the user. The `ConfigurationFactory` takes care that properties defined in the first file (the user file) are found; other properties which the user has not changed will still be returned from the second file (the defaults file).