For every project we have a staging environment that is almost always pretty much identical to the production environment. Of course you can’t completely mimick the production environment since systems we’re integrating with are not available (in which case they’re mocked) or located in a different place. We’re doing a lot Spring-based apps and some of the features Spring offers are really useful when distinguishing between a local environment, a staging environment and the final production environment. The following discusses the possibilities you have for setting up a Spring ApplicationContext to be able to deploy it to different environments without having to change the context itself.
PropertyPlaceHolderConfigurer
Spring offers two beans that allow you to externalize some of the properties in an ApplicationContext. The first and most often used one is the PropertyPlaceholderConfigurer. This bean allows you to include ${xxxyyyzzz} tokens in your application context and have them resolved at run-time (when the application context is loaded) from an external Properties file for example. An example would be the following:
<bean id='salesForceConnection'
class='icatch.salesforce.SalesForceConnectionImpl'
singleton='false'
init-method='init' destroy-method='close'>
<property name='url'>
<value>${salesforce.url}</value>
</property>
</bean>
The connection to the Salesforce service we’re integrating with is not mentioned in the context itself. Instead we are going to provide a separate Properties file and include it there. When deploying the application on the staging environment, we do not want to connect to the live Salesforce environment, but to the development edition instead. This offers the same features so we can still test everything. So based on the environment, we’re placing a different properties file in a pre-defined location and the application itself doesn’t need to change.
# staging.properties salesforce.url=\ https://na1-api.salesforce.com/services/Soap/c/3.0 #live.properties salesforce.url=\ https://emea.salesforce.com/services/Soap/c/2.5
Of course we still have to tell Spring where to find the properties it needs use when replacing the tokens. This is where the so-called BeanFactoryPostProcessor comes in. A post-processor is automatically executed after a context has fully finished loading all its bean definitions. This doesn’t mean any beans have been instantiated yet! The post-processor is allowed to inspect the application context and make changes as he wishes. One of those post-processor is the PropertyPlaceholderConfigurer. Configure it using the code snippet below. As you can see, we’ve put a Properties file in a pre-defined location and give it to the Spring placeholder configurer using the location property.
<bean class='org.spr.…config.PropertyPlaceholderConfigurer'> <propert name='location'> <value>/etc/icatch/sfconnection.properties</value> </propert></bean>
PropertyOverrideConfigurer
The example above shows an ApplicationContext with tokens that are replaced at run-time. Another option is to have default values in your context and have a PropertyOverrideConfigurer override those. This way you don’t always have to mention a configurer in your context and provide default values for development purposes. This would look something like the following:
<bean id='salesForceConnection'
class='icatch.salesforce.SalesForceConnectionImpl'
singleton='false'
init-method='init' destroy-method='close'>
<property name='url'>
<value>${salesforce.url}</value>
</property>
<property name='username'>
<value>blabbering</value>
</property>
<property name='password'>
<value>blabbering</value>
</property>
<property name='sessionTimeoutMS'>
<value>5400000</value> <!-- 1,5 hour -->
</property>
</bean>
#live-override.properties salesForceConnection.username=realusername salesForceConnection.password=realpassword
Choosing beans using a configurer
(overriding bean references)
One other nifty thing you can do using placeholder and override configurers is referencing a different bean based on a properties file. This feature is not really documented anywhere but can be handy sometimes. The configurers as they exist now only override and replace property values. In other words, they’re not capable of overriding and replacing complete bean definitions. The configurers are however able to override and replace bean references. This can be quite handy when you have more complex requirements and cannot do with simply replacing a property value:
<beans>
<bean class='org.spr.…config.PropertyPlaceholderConfigurer'>
<property name='properties'>
<props>
<prop key='connection.name'>connectionOne</prop>
</props>
</property>
</bean>
<bean id='service' class='ServiceObject'>
<property name='salesForceConnection'>
<ref bean='${connection.name}'/>
</property>
</bean>
<bean id='connectionOne' class='SuperConnection'>
<!-- other properties -->
</bean>
<bean id='connectionTwo' class='NotSoSuperConnection'>
<!-- other properties -->
</bean>
</beans>
Remember, usually one would split such a context in three files: one containing connectionTwo, one containing connectionOne and the other containing the service object. Based on what environment you’re in you would load a certain combinations of contexts. This is the way to go forward when selecting a data source implementation but the drawback here is that you need to override the bean itself. You cannot override the bean reference here. Using a PropertyPlaceholderConfigurer or PropertyOverrideConfigurer you can do that.
The location of your properties files
Then there is of course the issue of how to manage the different configurations. We usually have a configuration module in CVS where we keep directories for all different environments (one for staging, one for testing, one for production). Deploying a new version mean we have do the following:
- Deploy the new war file
- Overwrite the configuration directory with the directory we’ve pulled from CVS, specific to the current environment
So in case of the above examples, we’d have the following directory structure:
+-- staging - placeholder.properties - override.properties +-- production - placeholder.properties - override.properties

We do something very similar. We include, in every project, a dev.properties, qa.properties, and a prod.properties. Based on the ant command we give (ant dev, ant qa, or ant prod) we pull out that properties file and put it in our .war file. What’s nice is that individual developers can have their own configs (seth.properties), and just run ‘ant seth’ to build for seth’s configuration.
Alef,
Can I ask you something about configuration management of Spring. Can I use the JndiObjectFactoryBean to refer to a datasource that is already registered by a J2EE-container. My problem is that a DataSource will be configured by a administrator and that i just know the name. Where do i set the
property for the name and which property is this (is this ??
Maybe i see you soon. I work at Sogeti and heared that you people are giving seminars to us.
Gr. Haiko
Yes, that’s the exact purpose of the JndiObjectFactoryBean. The jndiName property (I believe) is what you need to use to set the jndi name. Something like this:
regards,
Alef
We use the file system implementation of the JNDI service com.sun.jndi.fscontext.RefFSContextFactory, and the PROVIDER_URL is
“file:/data/admin/jndi”. How should the JndiObjectFactoryBean be specified?
would give me an error message:
Can’t resolve reference to bean ‘file:/data/admin/jndi/jdbc/mytestdb’ while setting property ‘jndiName’; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException.
Alef, in your article, you state that when breaking out the bean definitions into multiple files (something I need to do), you can’t override the bean references. Is this because the beans are definted across multiple files? You then state that uUsing a PropertyPlaceholderConfigurer or PropertyOverrideConfigurer you can do that (I assume this means you can override the bean references). Can you provide some more direction on how to do this? Thanks.
Hi Keith,
I have limited access to internet at the moment. I’ll be at the office next week and hope not to forget to reply. Could you please remind me if I don’t?
thanks,
alef
Hi Alef,
your entry really helped me - thanks a lot!
I wonder if it is possible to define several different PropertyPlaceHolderConfigurer bean instances in one context?
I tried (even with adding the attribute “singleton=false”) but the first bean of this special class seems to override all others…
Kind regards, Stefan
Hi again,
after reading the source code of the PropertyPlaceHolderConfigurer class it seems as if it is not possible because the first bean factory post processor if this type throws an exception if it cannot resolve ALL properties it finds.
That’s a pity.
When different parts of an application want to externalize their configuration, they have to add their property file into the argument list of one central PropertyPlaceHolderConfigurer.
But you can’t have it all…
Stefan,
You can do this using the locations property of the PropertyPlaceHolderConfigurer, like this:
classpath:file1.properties
classpath:file2.properties
This worked for me in Spring 2.
OK, it escaped the quoted tags as invalid HTML tags despite me using the <code> tag.
Second attempt:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:xapi.properties</value>
<value>classpath:XapiServiceAuthenticator.properties</value>
</list>
</property>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:xapi.properties</value>
<value>classpath:XapiServiceAuthenticator.properties</value>
</list>
</property>
</bean>
Is there a way of overriding a collection? I have a list I need to override.
Thanks,
Steven
What directory are your .properties files in when deployed as part of a web application (i.e. in a .war file)? I’ve been asked to put them in WEB-INF/config directory on my current project. So, I can’t use classpath: in the locations list of the PropertyPlaceholderConfigurer. So, I specify /WEB-INF/config/acegi-security.properties (for example). This works fine except when I try to use the same Spring XML configuration files from a unit test. The other developers want to have Tomcat point to their project directory under the Eclipse workspace. So, the development environment has WebRoot/WEB-INF/config directory. Since, the Spring XML file specifies /WEB-INF/config, Eclipse and Ant expect a directory of WEB-INF/config under my top-level project directory.
Nathan
I figured out how to specify a path to property files in WEB-INF/config in the PropertyPlaceholderConfigurer location that works for both the web application as well for unit tests. The Ant style path can be specified: **/*/config/acegi-security.properties. For unit tests, I use a FilesystemXmlApplicationContext with paths of like WebRoot/WEB-INF/config/applicationContext.xml. The xml file has a PropertyPlaceholderConfigurer with the path as shown above.
Nathan,
yes, the fact that the PropertyPlaceholderConfigurer support Ant-style expressions is pretty neat.
I think I should start rewriting this blog post by the way; it has a lot of comments already and might need an update, also since we released Spring 2.0.
Maybe it’s just me, but your XML markup examples are hidden as the browser tries to render them as HTML. Try surrounding your markup with <xmp> tags.
Hello,
In our project we have to load property file at starting of application server and put those values in JNDI Context.
I tried to do so in spring using following
Using this it loads a property file but I am not able to see property values inside the file. How can I be able to achieve this in Spring MVC
is it a right way to do so?
Or if you have some idea about it will please help me in this.
Thanks & Regards
Abhijit
Hello, I’ve multiple PropertyPlaceholderConfigurer beans because in the application I’m working we add to the main Spring Context several context for different modules and I’m having problem with this because the context doesn’t find the placeholders but it doesn’t show problems in finding the .properties files. Does anybody kwnow something or had the same problem?
Thanks in advance!
Ulises
Ive had success overriding bean definitions just by specifiying a bean with the same id in a context file loaded after the master definitions.
If your web.xml has something like…
contextConfigLocation
classpath:app-defaults-spring.xml
classpath*:app-override-spring.xml
…then you can define a bean in app-override-spring.xml placed anywhere in the web app’s classpath, like in WEB-INF/classes. If the file is missing or not found, then the default definition will apply. Otherwise the defintion in app-override.xml will apply.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:app-defaults-spring.xml
classpath*:app-override-spring.xml
</param-value>
</context-param>
I’m fairly new to Spring but I have a project that’s very similar to the situation described above. There is ALOT of code that uses this one particular database object. Currently there are multiple files with the datasource information contained in each. I’m trying to find out if it is possible to specify a placeholder by checking for a system property and if it isn’t available using a default value.
Like I said, I’m very new to Spring, less than 1 week old, so I apologize if this is very basic.
Thanks for the post! I realize I could have found the information I needed in the Spring book at the spring sight, but this concise how-to write up gave me what I needed to know more quickly.
tqmk yozugl nrdf rcdpgbxhs syejv dirz iaft
Hi, it IS possible to have several PropertyPlaceHolderConfigurers. You just have to understand how the ordering affects the values and you must set the property ignoreUnresolvablePlaceholders to true on all but the PropertyPlaceHolderConfigurer loaded last (the one with the highest order-value).
The way it works is that the values set by the first PropertyPlaceHolderConfigurer cannot be overridden by PropertyPlaceHolderConfigurer loaded later.
Working like this makes it possible to spit the configuration in several contexts and let every context have its own PropertyPlaceHolderConfigurers which is responsible for the placeholders in its own context file.
Hi,
What about replacing values in constructor arguments? is it possible?
Yes certainly that possible. Just use the ${} format in the constructor-arg’s value attribute and you’re good to go.
Hi Alef,
I try to use PropertyPlaceholderConfigurer and I put my properties file in WEB-INF folder, but I get error FileNotFoundException. The properties name is spring.properties and when I run my application on tomcat, spring.properties can’t be found.
Below is my configuration of spring-config.xml:
/WEB-INF/spring.properties
And below is the code to create instance of bean factory:
BeanFactory factory = new ClassPathXmlApplicationContext(”/config/spring-config.xml”);
Do you know how to solve my problem?
Thanks
Hmm, the comments don’t seem to allow XML…
Anyway, your issues relates to you instantiating a ClassPathXmlApplicationContext. This context is only capable of reading resources from the classpath or from the file system. The default is the classpath and if you want to read stuff from the filesystem, you’d have to prefix your resource string with file:
You want to read resources from the /WEB-INF directory. This is done through the servlet context and as said, the ClassPathXmlApplicationContext can’t read stuff from the ServletContext.
Therefore what you’d have to do is instantiate a XmlWebApplicationContext and pass it the classpath:config/spring-config.xml string. The default for this ApplicationContext is to read from WEB-INF (throught he servlet context) so if in turn using this context you want to read from the classpath, you’d have to prefix your resource strings with classpath: (or file: for files from the filesystem).
Another way of doing it, is using a ContextLoaderListener. This element can be configured in web.xml (it’s a listener) and loads up an app ctx for you and puts it in the servlet context. Have a look at the reference manual for more info.
cheers,
Alef
Hi Alef,
The article gives a good reading.
I have an application level properties file configured using PropertyPlaceholderConfigurer. I use a ‘classpath:’ prefix to refer the properties file outside the .war application. For some reason, the properties file is not getting loaded during application deployment and throws a FileNotFoundException. And this happens only in a Linux Environment under Weblogic 8.1 server. The same works fine in a Windows box.
My bean configuration in applicationContext.xml goes like this…
[code]
classpath:app.properties
[/code]
And it throws the following exception….
[code][/code]
Any ideas why it does not work in a Linux env. ?
sorry, something got messed up with ‘code’ tags.. trying to paste it again…
User defined listener org.springframework.web.context.ContextLoaderListener failed: org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.FileNotFoundException: class path resource [app.properties] cannot be opened because it does not exist.