Externalizing part of the configuration of a webapp in a .properties file that is located outside of that webapp (outside the WAR, the EAR …) is a frequent requirement and I initially thought that the PropertyPlaceholderConfigurer class, provided by the Spring framework and which is an implementation of the BeanFactoryPostProcessor interface, would help me to get the values of the properties defined in that external file.
The properties are pulled into the application context definition file.
The typical sample code used to achieve this is the following :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>file:d:/temp/toto/myFile.properties</value> </list> </property </bean> <bean id="smtpserverurl" class="com.vendor.SomeSmtpServer"> <property name="URL" value="${smtpserver.url}"/> </bean>
or :
<context:property-placeholder location="file:d:/temp/toto/myFile.properties" /> <bean id="smtpserverurl" class="com.vendor.SomeSmtpServer"> <property name="URL" value="${smtpserver.url}"/> </bean>
And the properties file :
smtpserver.url=smtp.gmail.com
It is a good solution as long as you do not need dynamic reloading of the properties, i.e. without the need for restarting the application whenever the properties values are changed.
So I find out that in that case the Apache Commons Configuration is a good alternative because it supports dynamic reloading of the properties.
And it is as easy to use as this :
package com.celinio.readprops; import java.io.File; import java.util.Iterator; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; import org.apache.log4j.Logger; /** * This class reads properties that are stored in a file outside the webapp * @author Celinio Fernandes * */ public class ReadExternalPropertiesUtil { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(ReadExternalPropertiesUtil.class); private static final String PROPERTIES_FILE = "config.properties"; private static final String ENV_VAR = "PROPERTIES_APP"; public static String propertiesFolder; public static PropertiesConfiguration propertiesConfig = null; ... FileChangedReloadingStrategy strategy = null; strategy = new FileChangedReloadingStrategy(); strategy.setRefreshDelay(reloadInterval); propertiesConfig.setReloadingStrategy(strategy); propertiesConfig.setDelimiterParsingDisabled(true); ...
Line 23 : the path is given as an environment variable.
It works great. The only problem that I met was when I tested the reload interval (the delay period before the configuration file’s last modification date is checked again, to avoid permanent disc access on successive property lookups), it did not work : if i set the reload interval to 30 seconds for instance and if i modify the properties several times during that delay period, the new property values are still displayed. I would have expected to get the old values again, until the delay period expired.
The source code for this sample webapp is available at http://code.google.com/p/celinio/source/browse/#svn%2Ftrunk%2Fpropreloadable