Utility classes and Tips and TricksIn 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. Copy a configuration
Often it is required to copy the data of one
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:
Converting a flat configuration into a hierarchical oneHierarchical 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 Parameters params = new Parameters(); FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<PropertiesConfiguration>(PropertiesConfiguration.class) .configure(params.fileBased() .setFile(new File("config.properties")); PropertiesConfiguration flatConfig = builder.getConfiguration(); HierarchicalConfiguration<?> hc = ConfigurationUtils.convertToHierarchical(flatConfig);
The Sometimes a flat configuration contains keys with special characters that are not compatible with the expression engine of a hierarchical configuration. For instance, a properties configuration could have the following property: test(xy)=true
When processing this property during conversion the default expression
engine of the resulting hierarchical configuration will interpret the
brackets as an index marker and try to convert the string between the
brackets into a number. In this example this fails with a
To solve this problem, it is possible to specify an alternative expression
engine that will be used for the conversion. For instance, if you know that
your property keys can contain brackets, you could use an instance of
DefaultExpressionEngineSymbols symbols = new DefaultExpressionEngineSymbols.Builder( DefaultExpressionEngineSymbols.DEFAULT_SYMBOLS) .setIndexStart("[") .setIndexEnd("]") .create(); DefaultExpressionEngine engineConvert = new DefaultExpressionEngine(symbols); HierarchicalConfiguration<?> hc = ConfigurationUtils.convertToHierarchical(flatConfig, engineConvert); In this example an expression engine is constructed that uses square brackets as index markers. Therefore, normal brackets do not have a special meaning and thus do not cause problems during conversion any more.
Note: When using a
CombinedConfiguration flat configurations contained in the combined
configuration are also converted into hierarchical configurations using
the methods discussed here. The
Converting between properties and configurations
When working with the JDK the
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
/** * 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
Interpolation of all variables
Another issue with the integration of Commons Configuration with
native Java applications can be variables: Configuration implementations
are able to detect variables like
// Load a properties file (which may contain variables) Parameters params = new Parameters(); FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<PropertiesConfiguration>(PropertiesConfiguration.class) .configure(params.fileBased() .setFile(new File("config.properties")); PropertiesConfiguration config = builder.getConfiguration(); // Perform interpolation on all variables PropertiesConfiguration extConfig = (PropertiesConfiguration) config.interpolatedConfiguration(); // Save the interpolated configuration (no more variables) FileHandler handler = new FileHandler(extConfig); handler.save("external_config.properties"); Handling of runtime exceptions
Section Configuration Error Events
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
JNDIConfiguration config = new JNDIConfiguration(); ConfigurationUtils.enableRuntimeExceptions(config); // This may now throw a ConfigurationRuntimeException String value = config.getString("myKey");
Wrapping Configuration Builders
Section Creating Configurations
describes the concept of configuration builders as the preferred
way of creating configurations. The full flexibility of configuration
builders can be leveraged if an application holds a central builder
instance, and each time access to configuration information is needed,
this builder is queried for its managed
The concept of configuration builders has been introduced in version 2.0
of Commons Configuration. In older versions of this library
There is one helper class which can simplify this migration:
builder.getConfiguration().getString("key");
In order to create such a proxy wrapping a configuration builder, an
instance of // Create the builder to be wrapped Parameters params = new Parameters(); FileBasedConfigurationBuilder<Configuration> builder = new FileBasedConfigurationBuilder<Configuration>(PropertiesConfiguration.class) .configure(params.fileBased() .setFile(new File("config.properties")); // Create the wrapping proxy BuilderConfigurationWrapperFactory wrapperFactory = new BuilderConfigurationWrapperFactory(BuilderConfigurationWrapperFactory.EventSourceSupport.BUILDER); Configuration config = wrapperFactory.createBuilderConfigurationWrapper( Configuration.class, builder); Use Configuration in Spring
Commons Configuration integrates with the Spring framework.
A
CommonsConfigurationFactoryBean ).
As this library is no longer maintained, this is now supported directly by Commons Configuration.
If you've used this with Commons Configuration 1.x, just replace the spring-modules-jakarta-commons classname with
ConfigurationPropertiesFactoryBean .
Here is a sample xml configuration:
<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="properties"> <bean class="org.apache.commons.configuration2.spring.ConfigurationPropertiesFactoryBean"> <constructor-arg> <ref local="xmlConfiguration" /> </constructor-arg> </bean> </property> </bean>
In addition support as a @Value("${aPropertyKey}") private String configurationValue; @Configuration static class Config { @Bean public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(ConfigurableEnvironment env) throws ConfigurationException { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); MutablePropertySources sources = new MutablePropertySources(); sources.addLast(new ConfigurationPropertySource("xml configuration", new Configurations().xml("aXmlConfigFile.xml"))); configurer.setPropertySources(sources); configurer.setEnvironment(env); return configurer; } } |