| <?xml version="1.0"?> |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Configuration Factory Howto</title> |
| <author email="oliver.heger@t-online.de">Oliver Heger</author> |
| </properties> |
| |
| <body> |
| <section name="Using a Configuration Factory"> |
| <p> |
| This section explains how a |
| <code>ConfigurationFactory</code> object is setup that provides access |
| to a collection of different configuration sources. |
| </p> |
| |
| <subsection name="The configuration definition file"> |
| <p> |
| When a single configuration file (e.g. a properties file) is the only |
| source of configuration data it is very simple to |
| load it using the specific configuration class that deals with |
| the corresponding format (e.g. <code>PropertiesConfiguration</code> |
| for properties files or <code>XMLConfiguration</code> for XML files). But because |
| we think that later other sources will be added (otherwise |
| this example section would be too silly) we will use a |
| <code>ConfigurationFactory</code> object to load it. |
| </p> |
| <p> |
| <code>ConfigurationFactory</code> 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: |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <configuration> |
| <properties fileName="usergui.properties"/> |
| </configuration> |
| ]]></source> |
| <p> |
| Definition files for <code>ConfigurationFactory</code> are |
| normal XML files. The root element must be named |
| <code>configuration</code>. It can contain different sub |
| elements that specify the configuration sources to load. The |
| <code>properties</code> element is one of these; it is used to |
| include properties files. |
| </p> |
| <p> |
| For this example we store the definition file for |
| <code>ConfigurationFactory</code> in the same directory as the |
| properties file and call it <code>config.xml</code>. The |
| properties file used in this example is the same as in the |
| section about <a href="howto_properties.html">properties |
| files</a>. |
| </p> |
| </subsection> |
| <subsection name="Setting up a ConfigurationFactory"> |
| <p> |
| Now we have to create a <code>ConfigurationFactory</code> |
| 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 <code>setConfigurationFileName()</code> method. |
| </p> |
| <source><![CDATA[ |
| ConfigurationFactory factory = new ConfigurationFactory(); |
| URL configURL = new File("config.xml").toURL(); |
| factory.setConfigurationFileName(configURL.toString()); |
| Configuration config = factory.getConfiguration(); |
| ]]></source> |
| <p> |
| 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. |
| </p> |
| <p> |
| 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: |
| </p> |
| <source><![CDATA[ |
| ConfigurationFactory factory = new ConfigurationFactory(); |
| URL configURL = getClass().getResource("/config.xml"); |
| factory.setConfigurationURL(configURL); |
| Configuration config = factory.getConfiguration(); |
| ]]></source> |
| </subsection> |
| <subsection name="Accessing properties"> |
| <p> |
| Whatever way we used to load the configuration factory, we |
| should now have a <code>Configuration</code> object that was |
| returned by the factory's <code>getConfiguration()</code> |
| method. This object is actually an instance of the |
| <code>CompositeConfiguration</code> class, a specific implementation |
| of the <code>Configuration</code> interface that is able to |
| deal with multiple contained configuration objects. Of course |
| this class provides all the getter methods defined in the |
| <code>Configuration</code> interface, so for accessing a |
| string property for instance we would use the <code>getString()</code> method: |
| </p> |
| <source><![CDATA[ |
| String backColor = config.getString("color.background"); |
| ]]></source> |
| </subsection> |
| </section> |
| |
| <section name="Multiple configuration sources"> |
| <p> |
| Using <code>ConfigurationFactory</code> 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. |
| </p> |
| <subsection name="Overriding properties"> |
| <p> |
| 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: |
| </p> |
| <source><![CDATA[ |
| <?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> |
| ]]></source> |
| <p> |
| 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 <code>xml</code> |
| can be used so that we have now: |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <configuration> |
| <properties fileName="usergui.properties"/> |
| <xml fileName="gui.xml"/> |
| </configuration> |
| ]]></source> |
| <p> |
| The code for setting up the <code>ConfigurationFactory</code> |
| object remains the same. From the <code>Configuration</code> |
| object returned by the factory the new properties can be |
| accessed in the usual way. |
| </p> |
| <p> |
| There is one problem with this example configuration setup: |
| The <code>color.background</code> property |
| is defined in both the properties and the XML file, and - |
| to make things worse - with different values. Which value will |
| be returned by a call to <code>getString()</code>? |
| </p> |
| <p> |
| 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 <code>color.background</code> property can |
| be found in the properties file the value specified there will |
| be returned (which happens to be <code>#FFFFFF</code>). |
| </p> |
| <p> |
| 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 <code>ConfigurationFactory</code> 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). |
| </p> |
| </subsection> |
| <subsection name="Optional configuration sources"> |
| <p> |
| The example above with two configuration sources - one for user |
| settings and one with default values - raises an interesting |
| question: What will happen if the user has not defined specific |
| properties yet? Or what if a new user starts our application for |
| the first time and thus no user specific properties exist? |
| </p> |
| <p> |
| The default behavior of <code>ConfigurationFactory</code> is to |
| throw a <code>ConfigurationException</code> exception if one of |
| the sources defined in the configuration definition file cannot |
| be loaded. For our example this behavior is not desired: the |
| properties file with specific user settings is not required. If it |
| cannot be loaded, the example application will still work because |
| a complete set of configuration properties is defined in the |
| second file. |
| </p> |
| <p> |
| <code>ConfigurationFactory</code> supports such optional |
| configuration sources. For this purpose in the definition of a |
| (file based) configuration source the <code>optional</code> |
| attribute can be placed. An example of this is shown below: |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <configuration> |
| <properties fileName="usersettings.properties" optional="true"/> |
| <properties fileName="default.properties"/> |
| </configuration> |
| ]]></source> |
| <p> |
| In this configuration definition file the first properties file |
| with user specific settings is marked as optional. This means that |
| if it cannot be loaded, <code>ConfigurationFactory</code> will |
| not throw an exception, but only write a warning message to its |
| logger. Note that the <code>optional</code> attribute is absent |
| for the second properties file. Thus it is mandatory, and the |
| <code>getConfiguration()</code> method of |
| <code>ConfigurationFactory</code> would throw an exception if it |
| could not be found. |
| </p> |
| </subsection> |
| </section> |
| |
| <section name="Union configuration"> |
| <p> |
| In an earlier section about the configuration definition file for |
| <code>ConfigurationFactory</code> it was stated that configuration |
| files included first can override properties in configuraton files |
| included later and an example use case for this behaviour was given. |
| There may be times when there are other requirements. |
| </p> |
| <p> |
| Let's continue the example with the application that somehow process |
| database tables and that reads the definitions of the affected tables from |
| its configuration. This example and the corresponding XML configuration |
| files were introduced in the section about <a href="howto_xml.html">XMLConfiguration</a>. |
| Now consider that this application grows larger and |
| must be maintained by a team of developers. Each developer works on |
| a separated set of tables. In such a scenario it would be problematic |
| if the definitions for all tables would be kept in a single file. It can be |
| expected that this file needs to be changed very often and thus can be |
| a bottleneck for team development when it is nearly steadily checked |
| out. It would be much better if each developer had an associated file |
| with table definitions and all these information could be linked together |
| at the end. |
| </p> |
| <p> |
| <code>ConfigurationFactory</code> provides support for such a use case, |
| too. It is possible to specify in the configuration definition file that |
| from a set of configuration sources a logic union configuration is to be |
| constructed. Then all properties defined in the provided sources are |
| collected and can be accessed as if they had been defined in a single |
| source. To demonstrate this feature let us assume that a developer of |
| the database application has defined a specific XML file with a table |
| definition named <code>tasktables.xml</code>: |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <config> |
| <table tableType="application"> |
| <name>tasks</name> |
| <fields> |
| <field> |
| <name>taskid</name> |
| <type>long</type> |
| </field> |
| <field> |
| <name>name</name> |
| <type>java.lang.String</type> |
| </field> |
| <field> |
| <name>description</name> |
| <type>java.lang.String</type> |
| </field> |
| <field> |
| <name>responsibleID</name> |
| <type>long</type> |
| </field> |
| <field> |
| <name>creatorID</name> |
| <type>long</type> |
| </field> |
| <field> |
| <name>startDate</name> |
| <type>java.util.Date</type> |
| </field> |
| <field> |
| <name>endDate</name> |
| <type>java.util.Date</type> |
| </field> |
| </fields> |
| </table> |
| </config> |
| ]]></source> |
| <p> |
| This file defines the structure of an additional table, which should be |
| added to the so far existing table definitions. To achieve this the |
| configuration definition file has to be changed: A new section is added |
| that contains the include elements of all configuration sources which |
| are to be combined. |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| <!-- Configuration definition file that demonstrates the |
| override and additional sections --> |
| |
| <configuration> |
| <override> |
| <properties fileName="usergui.properties"/> |
| <xml fileName="gui.xml"/> |
| </override> |
| |
| <additional> |
| <xml fileName="tables.xml"/> |
| <xml fileName="tasktables.xml" at="tables"/> |
| </additional> |
| </configuration> |
| ]]></source> |
| <p> |
| Compared to the older versions of this file a couple of changes has been |
| done. One major difference is that the elements for including configuration |
| sources are no longer direct children of the root element, but are now |
| contained in either an <code>override</code> or <code>additional</code> |
| section. The names of these sections already imply their purpose. |
| </p> |
| <p> |
| The <code>override</code> section is not strictly necessary. Elements in |
| this section are treated as if they were children of the root element, i.e. |
| properties in the included configuration sources override properties in |
| sources included later. So the <code>override</code> tags could have |
| been ommitted, but for sake of clearity it is recommended to use them |
| when there is also an <code>additional</code> section. |
| </p> |
| <p> |
| It is the <code>additonal</code> section that introduces a new behaviour. |
| All configuration sources listed here are combined to a union configuration. |
| In our example we have put two <code>xml</code> elements in this area |
| that load the available files with database table definitions. The syntax |
| of elements in the <code>additional</code> section is analogous to the |
| syntax described so far. The only difference is an additionally supported |
| <code>at</code> attribute that specifies the position in the logic union |
| configuration where the included properties are to be added. In this |
| example we set the <code>at</code> attribute of the second element to |
| <em>tables</em>. This is because the file starts with a <code>table</code> |
| element, but to be compatible with the other table definition file it should be |
| accessable under the key <code>tables.table</code>. |
| </p> |
| <p> |
| After these modifications have been performed the configuration obtained |
| from the <code>ConfigurationFactory</code> will allow access to three |
| database tables. A call of <code>config.getString("tables.table(2).name");</code> |
| will result in a value of <em>tasks</em>. In an analogous way it is possible |
| to retrieve the fields of the third table. |
| </p> |
| <p> |
| Note that it is also possible to override properties defined in an |
| <code>additonal</code> section. This can be done by placing a |
| configuration source in the <code>override</code> section that defines |
| properties that are also defined in one of the sources listed in the |
| <code>additional</code> section. The example does not make use of that. |
| Note also that the order of the <code>override</code> and |
| <code>additional</code> sections in a configuration definition file does |
| not matter. Sources in an <code>override</code> section are always treated with |
| higher priority (otherwise they could not override the values of other |
| sources). |
| </p> |
| </section> |
| |
| <section name="The configuration definition file"> |
| <p> |
| We have seen how to write configuration definition files for |
| including properties and XML files. This section deals with other |
| options that can be specified in such a definition file and that |
| are evaluated by <code>ConfigurationFactory</code>. |
| </p> |
| <p> |
| From time to time the question is raised whether there is a |
| document type definition that exactly defines the structure of a |
| configuration definition file. Frankly, the answer is no. This is |
| because for a future version of Commons Configuration it is planed |
| to make the configuration definition files extensible, i.e. allow |
| developers to register their own tags and corresponding implementations |
| of the Configuration interface. |
| </p> |
| <p> |
| In the current version the set of supported XML elements is fixed. |
| Below is a list of all supported tags and a description of each: |
| </p> |
| <p> |
| <dl> |
| <dt>properties</dt> |
| <dd> |
| With this element properties files can be included. The name of |
| the file to load is specified using the <code>fileName</code> |
| attribute. Which configuration class is created by this tag |
| depends on the extension of the file to load: If the extension |
| is ".xml", a <code>XMLPropertiesConfiguration</code> object is |
| created, which is able to process the XML properties format |
| introduced in Java 5.0. Otherwise a <code>PropertiesConfiguration</code> |
| object is created, the default reader for properties files. |
| </dd> |
| <dt>xml</dt> |
| <dd> |
| The <code>xml</code> element can be used to load XML configuration |
| files. It also uses the <code>fileName</code> attribute to |
| determine the name of the file to load and creates an instance |
| of <code>XMLConfiguration</code>. |
| </dd> |
| <dt>jndi</dt> |
| <dd> |
| As the name implies, with this element JNDI resources can be |
| included in the resulting configuration. Under the hood this is |
| done by an instance of the <code>JNDIConfiguration</code> |
| class. The <code>prefix</code> attribute can be used to |
| select a subset of the JNDI tree. |
| </dd> |
| <dt>plist</dt> |
| <dd> |
| The <code>plist</code> element allows to embedd configuration |
| files in the NeXT / OpenStep or Mac OS X format. Again the |
| name of the file to load is specified through the |
| <code>fileName</code> attribute. If a XML file is specified, |
| a <code>XMLPropertyListConfiguration</code> object is created |
| to process the file. Otherwise this task is delegated to a |
| <code>PropertyListConfiguration</code> instance. |
| </dd> |
| <dt>system</dt> |
| <dd> |
| With this element an instance of <code>SystemConfiguration</code> |
| is added to the resulting configuration allowing access to |
| system properties. |
| </dd> |
| </dl> |
| </p> |
| <p> |
| All of these elements can occur in a configuration definition file |
| in arbitrary number and order. The following listing shows an |
| example file using many of these tags. |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <configuration> |
| <system/> |
| <jndi prefix="java:comp/env"/> |
| <properties fileName="test.properties"/> |
| <xml fileName="test.xml"/> |
| <properties fileName="test.properties.xml"/> |
| </configuration> |
| ]]></source> |
| |
| <subsection name="Setting further options"> |
| <p> |
| Many specialized configuration classes support initialization |
| properties that influence the behavior of their instances. For |
| example for file based configurations the encoding of the files |
| to load can be specified using the <code>setEncoding()</code> |
| method, or an <code>XMLConfiguration</code> can be told to |
| perform validation by calling the <code>setValidating()</code> |
| method. How can such properties be set in a configuration definition |
| file? |
| </p> |
| <p> |
| Fortunately this is easy possible. For each XML element in a |
| configuration definition file additional attributes can be |
| specified that correspond to (bean) setter methods defined in the |
| associated configuration class. To derive the name of an attribute |
| from a setter method to be called, just drop the prefix "set" and |
| make the first letter lower case. So for instance the attribute |
| that invokes the <code>setEncoding()</code> method would be |
| <code>encoding</code>. The following example shows how a XML |
| document with a certain encoding and enabled validation can be |
| loaded: |
| </p> |
| <source><![CDATA[ |
| <?xml version="1.0" encoding="ISO-8859-1" ?> |
| |
| <configuration> |
| <xml fileName="test.xml" encoding="UTF-8" validating="true"/> |
| </configuration> |
| ]]></source> |
| <p> |
| Using this mechanism many properties of configuration classes can |
| be set when they are used together with <code>ConfigurationFactory</code>. |
| To find out, which attributes are supported by a specific XML |
| element, refer to the list in the previous section that explains, |
| which configuration classes are used for which tags. In the JavaDoc |
| of the corresponding class you can find the setter methods you can |
| address by attributes. |
| </p> |
| </subsection> |
| </section> |
| </body> |
| |
| </document> |