Copied: commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml (from r713226, commons/proper/configuration/trunk/xdocs/userguide/howto_filebased.xml) URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml?p2=commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml&p1=commons/proper/configuration/trunk/xdocs/userguide/howto_filebased.xml&r1=713226&r2=719319&rev=719319&view=diff ============================================================================== --- commons/proper/configuration/trunk/xdocs/userguide/howto_filebased.xml (original) +++ commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml Thu Nov 20 10:33:04 2008 @@ -18,227 +18,131 @@ <document> - <properties> - <title>File-based Configurations</title> - <author email="[EMAIL PROTECTED]">Oliver Heger</author> - </properties> - -<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> - - <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="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> - - <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); -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> - </subsection> - - <subsection name="Automatic Reloading"> - <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. - </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> + <properties> + <title>Mutli-tenant Configurations</title> + <author email="[EMAIL PROTECTED]">Ralph Goers</author> + </properties> + + <body> + <section name="Multi-tenant Configurations"> + <p> + In a multi-tenant environment a single instance of the application + while run on behalf of many clients. Typically, this will require + that each client have its own unique configuration. The simplest + approach to enable an application to be multi-tenant is for it + to not really be aware of it at all. This requires that the + configuration framework take on some of the responsility for + making the application work correctly. + </p> + <p> + One approach to enable this support in a web application might be + to use a Servlet Filter and then use the Log4j or SLF4J MDC to + save the attributes needed to identify the client. These attributes + can then be used to identify the specific client configuration to + be used. The classes described below use this technique to allow + configurations to transparently provide the configuration appropriate + for the clients. + </p> + + <subsection name="MultiFileHierarchicalConfiguration"> + <p> + The constructor for this class accepts a pattern. The pattern can + contain keys that will be resolved using the ConfigurationInterpolator + on each call to a method in the class. The configuration file will then + be located using the resolved pattern and a new XMLConfiguration + will be created and cached for subsequent requests. The ExpressionEngine, + ReloadingStrategy and listeners will be propogated to each of the + created configurations. + </p> + </subsection> + <subsection name="DynamicCombinedConfiguration"> + <p> + The CombinedConfiguration class allows multiple configuration files to be + merged together. However, it will not merge a MultiFileHierarchicalConfiguration + properly since the underlying configuration file will be different depending + on the resolution of the location pattern. DynamicCombinedConfiguration + solves this by creating a new CombinedConfiguration for each pattern. + </p> + </subsection> + <subsection name="Sample Configuration"> + <p> + This sample configuration illustrates how to use DynamicCombinedConfiguration + in combination with MultiFileHierarchicalConfiguration to create a multi-tenant + configuration. + </p> + <source><![CDATA[ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!-- Test configuration definition file that demonstrates complex initialization --> +<configuration> + <header> + <result delimiterParsingDisabled="true" forceReloadCheck="true" + config-class="org.apache.commons.configuration.DynamicCombinedConfiguration" + keyPattern="${sys:Id}"> + <expressionEngine + config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/> + </result> + <providers> + <provider config-tag="multifile" + config-class="org.apache.commons.configuration.DefaultConfigurationBuilder$FileConfigurationProvider" + configurationClass="org.apache.commons.configuration.MultiFileHierarchicalConfiguration"/> + </providers> + </header> + <override> + <multifile filePattern="/opt/configs/${sys:Id}/config.xml" config-name="clientConfig"/> + <xml fileName="/opt/configs/default/config.xml" config-name="defaultConfig"/> + </override> +</configuration> +]]></source> + </subsection> + <subsection name="PatternSubtreeConfigurationWrapper"> + <p> + Applications are often composed of many components each of which need their + own configuration. This can be accomodated by having a configuration file + per component, but this can make things hard to manage when there are many + clients and many components. A second approach is to combine them into + a single configuration file. However, this either means the subcomponent + has to be aware of the surrounding configuration and navigate past it or the + application must be provided just the portion of the configuration it + can process. PatternSubtreeConfigurationWrapper can be used for this purpose. + </p> + <p> + Normal practice when using dependency injection frameworks is to have the + attributes needed to make components work correctly injected into them. + When working with Commons Configuration this works very well. Components + simply need to have a HierarchicalConfiguration attribute along with + a corresponding setter and getter. The injection framework can then be + used to provide the component with the correct configuration using + PatternSubtreeConfigurationWrapper as shown in the next example. + </p> + <p> + <source><![CDATA[ + <bean id="configurationBuilder" + class="org.apache.commons.configuration.DefaultConfigurationBuilder"> + <property name="fileName"> + <value>configuration.xml</value> </property> -</bean> -]]> -</source> - With this configuration, the JMX console will expose the - "myApp:bean=configuration" MBean and it's refresh operation. + </bean> + <bean id="applicationConfig" factory-bean="configurationBuilder" + factory-method="getConfiguration"> + </bean> + <bean id="subcomponentConfig" + class="org.apache.commons.configuration.PatternSubtreeConfigurationWrapper" + autowire='autodetect'> + <constructor-arg index="0"> + <ref bean="applicationConfig"/> + </constructor-arg> + <constructor-arg index="1" value="/Components/MyComponent" + </bean> + <bean id='MyComponent' class='org.test.MyComponent' autowire='autodetect'> + <property name="configuration"> + <ref bean="subcomponentConfig"/> + </property> + </bean> +]]></source> </p> - </subsection> + </subsection> </section> -</body> + </body> </document>
Propchange: commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Propchange: commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml ------------------------------------------------------------------------------ svn:mergeinfo = Propchange: commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml ------------------------------------------------------------------------------ svn:mime-type = text/xml Modified: commons/proper/configuration/trunk/xdocs/userguide/user_guide.xml URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/xdocs/userguide/user_guide.xml?rev=719319&r1=719318&r2=719319&view=diff ============================================================================== --- commons/proper/configuration/trunk/xdocs/userguide/user_guide.xml (original) +++ commons/proper/configuration/trunk/xdocs/userguide/user_guide.xml Thu Nov 20 10:33:04 2008 @@ -132,6 +132,13 @@ <li><a href="howto_configurationbuilder.html#An_example">An example</a></li> <li><a href="howto_configurationbuilder.html#Extending_the_configuration_definition_file_format">Extending the configuration definition file format</a></li> </ul> + <li><a href="howto_multitenant.html#Multi-tenant Configurations">Multi-tenant Configurations</a></li> + <ul> + <li><a href="howto_multitenant.html#MultiFileHierarchicalConfiguration">MultiFileHierarchicalConfiguration</a></li> + <li><a href="howto_multitenant.html#DynamicCombinedConfiguration">DynamicCombinedConfiguration</a></li> + <li><a href="howto_multitenant.html#Sample Configuration">Sample Configuration</a></li> + <li><a href="howto_multitenant.html#PatternSubtreeConfigurationWrapper">PatternSubtreeConfigurationWrapper</a></li> + </ul> <li><a href="howto_events.html#Configuration_Events">Configuration Events</a></li> <ul> <li><a href="howto_events.html#Configuration_listeners">Configuration listeners</a></li>