Author: oheger
Date: Sun May 11 17:48:54 2014
New Revision: 1593827

URL: http://svn.apache.org/r1593827
Log:
Reworked chapter about file-based configurations in user guide.

Modified:
    
commons/proper/configuration/trunk/src/site/xdoc/userguide/howto_filebased.xml

Modified: 
commons/proper/configuration/trunk/src/site/xdoc/userguide/howto_filebased.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/site/xdoc/userguide/howto_filebased.xml?rev=1593827&r1=1593826&r2=1593827&view=diff
==============================================================================
--- 
commons/proper/configuration/trunk/src/site/xdoc/userguide/howto_filebased.xml 
(original)
+++ 
commons/proper/configuration/trunk/src/site/xdoc/userguide/howto_filebased.xml 
Sun May 11 17:48:54 2014
@@ -26,216 +26,258 @@
 <body>
     <section name="File-based Configurations">
         <p>
-            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 <code>java.io.File</code> objects,
-          relative or absolute path names, or URLs.
-        </p>
-        <p>
-          To provide a consistent way of dealing with configuration files in
-          Commons Configuration the <code><a 
href="../apidocs/org/apache/commons/configuration/FileConfiguration.html">FileConfiguration</a></code>
-          interface exists. <code>FileConfiguration</code> defines a standard
-          API for accessing files and is implemented by many configuration
-          implementations, including <code>PropertiesConfiguration</code> and
-          <code>XMLConfiguration</code>.
-        </p>
-        <p>
-          In the following sections we take a closer look at the methods of the
-          <code>FileConfiguration</code> interface and how they are used.
-        </p>
-
-        <subsection name="Specifying the file">
-          <p>
-            The <code>FileConfiguration</code> interface contains several
-            methods for specifying the file to be loaded. The following 
variants
-            are supported:
-            <ul>
-              <li>With the <code>setFile()</code> method the data file can be
-              specified as a <code>java.io.File</code> object.</li>
-              <li>The <code>setURL()</code> takes a <code>java.net.URL</code>
-              as argument; the file will be loaded from this URL.</li>
-              <li>The methods <code>setFileName()</code> and 
<code>setBasePath()</code>
-              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.</li>
-            </ul>
-          </p>
-          <p>
-            While a <code>File</code> or a URL uniquely identify a file, the
-            situation is a bit ambigous 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):
-            <ul>
-              <li>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.</li>
-              <li>If the combination from base path and file name is an 
absolute
-              file name and this file exists, it will be loaded.</li>
-              <li>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.</li>
-              <li>If a file with the specified name exists in the user's home
-              directory, this file will be loaded.</li>
-              <li>Otherwise the file name is interpreted as a resource name, 
and
-              it is checked whether the data file can be loaded from the 
classpath.</li>
-            </ul>
-            If all these checks fail, a <code>ConfigurationException</code> 
will
-            be thrown.
-          </p>
-        </subsection>
+          Often configuration properties are stored in files on the user's hard
+          disk, e.g. in .properties files or as XML documents. In order to
+          access this data, functionality is needed to select the configuration
+          files, load them into memory, and write changes back to disk. The
+          following sections describe how this can be done.
+        </p>
 
-        <subsection name="Loading">
-          <p>
-            After the file name has been defined using one of the methods 
mentioned
-            above, the <code>load()</code> method can be called. This method 
tries
-            to locate the file and open it. If this fails, a 
<code>ConfigurationException</code>
-            is thrown.
-          </p>
-          <p>
-            The <code>FileConfiguration</code> interface defines multiple 
overloaded
-            <code>load()</code> 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 <code>java.io.File</code>, <code>java.net.URL</code>, 
string
-            (containing either an absolute or relative path), input stream, or
-            reader. When using these variants of the <code>load()</code> method
-            be aware of two things:
-            <ol>
-              <li>They do not change the configuration's file name. To do this
-              you have to explicitely call one of the setter methods.</li>
-              <li>The <code>load()</code> methods do not empty the
-              configuration before new data is loaded. This makes it easy to
-              construct union configurations by simply calling 
<code>load()</code>
-              multiple times. But if you want to reuse a 
<code>Configuration</code>
-              object and load a different file, remember to call the
-              <code>clear()</code> method first to ensure that old properties 
are
-              wiped out.</li>
-            </ol>
-          </p>
-          <p>
-            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 
<code>load()</code>
-            method. So creating a file-based configuration object and loading 
its
-            content can be done in a single step.
-          </p>
-        </subsection>
+        <subsection name="FileBasedConfigurationBuilder">
+        <p>
+          In <em>Commons Configuration</em> a specialized
+          <a href="howto_builders.html#Configuration_Builders">configuration
+          builder</a> implementation is responsible for the creation of
+          file-based configuration objects and the management of their
+          associated data files:
+          <code><a 
href="../apidocs/org/apache/commons/configuration/builder/FileBasedConfigurationBuilder.html">
+          FileBasedConfigurationBuilder</a></code>. Usage of this class follows
+          the typical pattern for configuration builders, i.e. a builder
+          instance is created providing the class of the 
<code>Configuration</code>
+          object to be created, the <code>configure()</code> method is called
+          with initialization parameters, and finally 
<code>getConfiguration()</code>
+          returns an initialized instance of the configuration class. When
+          configuring the builder the file to be loaded can be specified; if 
this
+          was done, the <code>Configuration</code> object returned by the
+          builder contains all properties read from the underlying file.
+        </p>
+        <p>
+          In order to define the file to be loaded, a parameters object
+          implementing the
+          <code><a 
href="../apidocs/org/apache/commons/configuration/builder/FileBasedBuilderProperties.html">
+          FileBasedBuilderProperties</a></code> interface can be passed to the
+          builder's <code>configure()</code> method. Using this interface the
+          location of the file to be loaded can be provided in multiple ways:
+          <ul>
+            <li>With the <code>setFile()</code> method the data file can be
+            specified as a <code>java.io.File</code> object.</li>
+            <li>The <code>setURL()</code> method takes a 
<code>java.net.URL</code>
+            as argument; the file will be loaded from this URL.</li>
+            <li>The methods <code>setFileName()</code> and 
<code>setBasePath()</code>
+            allow specifying the path of the data file. The base path is
+            important if relative paths are to be resolved based on this 
file.</li>
+            <li>With <code>setPath()</code> an absolute path to the file to be
+            loaded can be provided.</li>
+          </ul>
+          As an example, the following code fragment shows how a properties
+          file can be read whose location is specified using a 
<code>File</code>
+          object:
+        </p>
+        <source><![CDATA[
+Parameters params = new Parameters();
+// Read data from this file
+File propertiesFile = new File("config.properties");
 
-        <subsection name="Saving">
-          <p>
-            Saving is implemented analogously to loading: There is a no 
argument
-            <code>save()</code> method that will use the internal file name. 
Then
-            for each <code>load()</code> method a corresponding 
<code>save()</code>
-            method exists that will write the data contained in the 
configuration
-            to different targets.
-          </p>
-          <p>
-            An example for loading, manipulating, and saving a configuration
-            (based on a <a 
href="howto_properties.html"><code>PropertiesConfiguration</code></a>)
-            could look as follows:
-          </p>
-<source>
-PropertiesConfiguration config = new 
PropertiesConfiguration("usergui.properties");
-config.setProperty("colors.background", "#000000");
-config.save();
-</source>
-          <p>
-            You can also save a copy of the configuration to another file:
-          </p>
-<source>
-PropertiesConfiguration config = new 
PropertiesConfiguration("usergui.properties");
-config.setProperty("colors.background", "#000000");
-config.save("usergui.backup.properties);
-</source>
-        </subsection>
+FileBasedConfigurationBuilder<Configuration> builder =
+    new 
FileBasedConfigurationBuilder<Configuration>(PropertiesConfiguration.class)
+    .configure(params.fileBased()
+        .setFile(propertiesFile));
+try
+{
+    Configuration config = builder.getConfiguration();
+    // config contains all properties read from the file
+}
+catch(ConfigurationException cex)
+{
+    // loading of the configuration file failed
+}]]></source>
+        <p>
+          In this example a parameters object for file-based configurations
+          is obtained from a <code>Parameters</code> instance. We could of
+          course also have used a derived parameters class - when loading a
+          properties file a parameters object for properties configurations
+          would have been a logic choice. Here only a single parameter, the
+          file to be loaded, is set; but remember that all other initialization
+          parameters common to all configuration classes are available as well.
+        </p>
+       <p>
+         A configuration instance created this way stays connected to its
+         builder. Especially, the builder stores the location of the
+         underlying configuration file. This comes in handy if changes on
+         the configuration object are to be written back to disk. For this
+         purpose, <code>FileBasedConfigurationBuilder</code> provides a
+         convenient <code>save()</code> method. Calling this method stores
+         the current content of the associated configuration into its original
+         configuration file, overwriting the existing file on disk. This is
+         demonstrated in the following code fragment which continues from the
+         previous example:
+       </p>
+        <source><![CDATA[
+// Some manipulations on the configuration object
+config.addProperty("newProperty", "new");
+config.setProperty("updateProperty", "changedValue");
+
+// Make changes persistent
+try
+{
+    builder.save();
+}
+catch(ConfigurationException cex)
+{
+    // saving of the configuration file failed
+}]]></source>
+       <p>
+         Note that the <code>save()</code> method of the builder does not
+         expect a configuration object as parameter. It always operates on
+         the instance managed by this builder. Because of this relationship
+         it is typically better to store the builder object rather than the
+         configuration. The configuration can always be obtained via the
+         builder's <code>getConfiguration()</code> method, but operations
+         related to the configuration file are only available through the
+         builder.
+       </p>
+       <p>
+         In addition to the <code>save()</code> method,
+         <code>FileBasedConfigurationBuilder</code> offers functionality for
+         automatically saving changes on its managed configuration. This can
+         be used to ensure that every modification of a configuration object is
+         immideately written to disk. This feature is enabled via the
+         <code>setAutoSave()</code> method as shown in the following example:
+       </p>
+        <source><![CDATA[
+FileBasedConfigurationBuilder<Configuration> builder =
+    new 
FileBasedConfigurationBuilder<Configuration>(PropertiesConfiguration.class)
+    .configure(params.fileBased()
+        .setFile(new File("config.properties")));
+// enable auto save mode
+builder.setAutoSave(true);
 
-        <subsection name="Automatic Saving">
-          <p>
-            If you want to ensure that every modification of a configuration
-            object is immideately written to disk, you can enable the automatic
-            saving mode. This is done through the <code>setAutoSave()</code>
-            method as shown in the following example:
-          </p>
-<source>
-PropertiesConfiguration config = new 
PropertiesConfiguration("usergui.properties");
-config.setAutoSave(true);
+Configuration config = builder.getConfiguration();
 config.setProperty("colors.background", "#000000"); // the configuration is 
saved after this call
-</source>
-          <p>
-            Be careful with this mode when you have many updates on your
-            configuration. This will lead to many I/O operations, too.
-          </p>
+]]></source>
+       <p>
+         Be careful with this mode when you have many updates on your
+          configuration. This will lead to many I/O operations, too. Behind
+          the scenes, automatic saving is implemented via the
+          <a href="howto_events.html">event notification mechanism</a> 
available
+          for all configuration objects. A specialized event listener is
+          registered at the builder's managed configuration object which 
triggers
+          the <code>save()</code> method every time an update event is 
received.
+       </p>
         </subsection>
 
-        <subsection name="Automatic Reloading">
+        <subsection name="File Operations on Configurations">
         <p>
-          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 <em>reloading strategies</em> 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 <code><a 
href="../apidocs/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.html">FileChangedReloadingStrategy</a></code>.
-          It can be set on a file-based configuration as follows:
-        </p>
-<source>
-PropertiesConfiguration config = new 
PropertiesConfiguration("usergui.properties");
-config.setReloadingStrategy(new FileChangedReloadingStrategy());
-</source>
-        <p>
-          <code>FileChangedReloadingStrategy</code> works as follows: On every
-          property access the configuration checks its associated reloading
-          strategy. <code>FileChangedReloadingStrategy</code> 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 <em>refresh delay</em> 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.
+          With <code>FileBasedConfigurationBuilder</code> a single 
configuration
+          file is assigned to a configuration instance. For some use cases a
+          more flexible approach is required. For instance, a modified
+          configuration is to be stored in another file, or multiple 
configuration
+          files should be loaded into the same instance. To achieve this, the
+          underlying mechanisms for dealing with files have to be used.
+        </p>
+        <p>
+          I/O operations on files are controlled by the
+          <code><a 
href="../apidocs/org/apache/commons/configuration/io/FileHandler.html">
+          FileHandler</a></code> class. Basically, this class connects a 
location
+          of a configuration file (and some other meta information like the
+          file's encoding) with an object which can read data from or write 
data
+          to this location. <code>FileHandler</code> defines the typical
+          properties for defining the file to be loaded, i.e. the location can 
be
+          specified as a URL, a File, an absolute path, etc.
+        </p>
+        <p>
+          The object which actually reads and writes the data is represented 
by the
+          <code><a 
href="../apidocs/org/apache/commons/configuration/io/FileBased.html">
+          FileBased</a></code> interface. This is a pretty lean interface
+          consisting of only two methods for reading data from a Reader and
+          writing data to a Writer. All configuration implementations that can
+          be initialized from configuration files implement this interface; but
+          in theory the <code>FileHandler</code> could interact with other
+          objects implementing <code>FileBased</code> as well.
+        </p>
+        <p>
+          <code>FileHandler</code> has the two methods <code>load()</code> and
+          <code>save()</code>. They work as follows:
+          <ul>
+            <li>The location of the managed file is evaluated, and a 
corresponding
+            stream is opened. Depending on the way the location was specified,
+            this could mean opening a connection on a URL, opening a stream to
+            a <code>File</code> or an absolute path name, resolving relative
+            file names, etc.</li>
+            <li>The resulting stream is then passed to the associated
+            <code>FileBased</code>'s <code>read()</code> or 
<code>write()</code>
+            method.</li>
+          </ul>
+        </p>
+        <p>
+          Next to these simple <code>load()</code> and <code>save()</code>
+          methods a number of overloaded methods exists which expect additional
+          parameters defining the source or target of the operation. For
+          instance, there is a <code>load(URL)</code> method which reads data
+          directly from the passed in URL ignoring the location stored in the
+          <code>FileHandler</code> instance. In fact, there are overloaded
+          methods for all the supported variants for defining a file. When
+          making use of these methods the following points have to be kept in
+          mind:
+          <ul>
+            <li>The location stored in the <code>FileHandler</code> instance is
+            not changed; it is completely by-passed bythese methods. Only
+            explicite calls to thevarious  setter methods modify the 
location.</li>
+            <li>The <code>load()</code> methods eventually call the target
+            object's <code>read()</code> method, no matter if it has already 
been
+            called before. For configuration objects as target this means that
+            the configuration is not cleared before new data is loaded.
+            (Actually a <code>FileHandler</code> is not aware which kind of
+            target object it is serving; so it has no chance to clear it 
first.)
+            This behavior makes it easy to construct union configurations by
+            simply executing multiple load operations. But if you want to reuse
+            a configuration object and load a different file, remember to call 
the
+            <code>clear()</code> method first to ensure that old properties are
+            wiped out.</li>
+          </ul>
         </p>
-        </subsection>
-
-        <subsection name="Managed Reloading">
         <p>
-          <code>ManagedReloadingStrategy</code> is an alternative to automatic
-          reloading. It allows to hot-reload properties on a running 
application
-          but only when requested by admin. The <code>refresh()</code> method
-          will force a reload of the configuration source.
-        </p>
-        <p>
-          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 :
-<source>
-<![CDATA[
-<!-- 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>
-]]>
-</source>
-          With this configuration, the JMX console will expose the
-          "myApp:bean=configuration" MBean and it's refresh operation.
+          When constructing a <code>FileHandler</code> instance the
+          <code>FileBased</code> object it operates on has to be passed to the
+          constructor. With this information we are now able to look at a
+          concrete example. The goal is to create a configuration for a
+          properties file, read in another properties file (so that a union of
+          the properties is constructed), and finally write the resulting
+          configuration to a new file. The code can look as follows (the
+          handling of exceptions has been omitted):
         </p>
+        <source><![CDATA[
+// Read first file directly via the builder
+FileBasedConfigurationBuilder<PropertiesConfiguration> builder =
+    new 
FileBasedConfigurationBuilder<Configuration>(PropertiesConfiguration.class)
+    .configure(params.fileBased()
+        .setFile(new File("config.properties")));
+PropertiesConfiguration config = builder.getConfiguration();
+
+// Create a file handler and associate it with the configuration
+FileHandler handler = new FileHandler(config);
+
+// Load another configuration source, for instance from a relative path
+handler.load("user.properties");
+
+// Store the resulting configuguration in a new file
+File out = new File("union.properties");
+handler.save(out);
+]]></source>
+       <p>
+         The <code>FileHandler</code> class is thread-safe; it is no problem
+         for instance to define a file location in one thread and then call
+         <code>load()</code> on another thread. It is also possible to have
+         multiple <code>FileHandler</code> objects associated with the same
+         target object. Here concurrent I/O operations could cause problems.
+         Therefore, <code>FileHandler</code> checks whether the target object
+         implements the
+         <code><a 
href="../apidocs/org/apache/commons/configuration/sync/SynchronizerSupport.html">
+          SynchronizerSupport</a></code> interface. If this is the case, proper
+          synchronization for load and save operations can be performed. 
Because
+          all configuration implementations implement 
<code>SynchronizerSupport</code>
+          they can safely be used together with <code>FileHandler</code>.
+       </p>
         </subsection>
     </section>
 


Reply via email to