Project Configuration with Spring

The .properties files
Considering the following types of environments that we want to cover – dev, staging, production – we will need to create the following properties files: persistence-dev.properties, persistence-staging.properties and persistence-production.properties. In a typical Maven application, these can reside in src/main/resources, but the wherever they are, they will need to be available on the classpath when the application is deployed.

Since all properties files will be under version control alongside the rest of the codebase, all environment configurations will be transparent and fully reproducible. This comes in extremely handy in cases where a specific production environment must be quickly reproduced so that an issue can be debugged or verified.

Spring configuration

In Spring, the correct properties file needs to be used based on the environment:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="

http://www.springframework.org/schema/beans


http://www.springframework.org/schema/beans/spring-beans-3.1.xsd


http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd">
      <context:property-placeholder
         location="
         classpath*:*persistence-${envTarget}.properties" />
</beans>

If Spring 3.1 is used, this configuration will create a PropertySourcesPlaceholderConfigurer which will add the properties defined in the file to the Spring Environment abstraction. For older versions of Spring, the older PropertyPlaceholderConfigurer will be created for dealing with the properties. For more details on the newly introduced Environment abstraction and properties support, see the previous Properties with Spring article.

This approach allows for the flexibility of having multiple *.properties files for specific, focused purposes – the persistence related properties can be grouped together in their own persistence-*.properties file, while other concerns can have their own .properties files. The common properties that are global to the application but do not change based on the environment can simply be added in an unique common.properties file.

Setting the Property in each environment

The final, deployable war will contain all properties files – for persistence, the three variants of persistence-*.properties. Since the files are actually named differently, there is no fear of accidentally working against the wrong one – by setting the envTarget variable, we will strongly select a single instance of the multiple existing variants.
The envTarget variable can be set in the OS/environment or as a parameter to the JVM command line:

-DenvTarget=dev

Maven and testing

Some integration tests need to have persistence enabled, but obviously not the same provider/schema as a standard environment. The flexibility of the current solution is perfect for this use case – the Maven pom.xml will need to simply specify the envTarget variable for testing:

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-surefire-plugin</artifactId>
   <configuration>
      <systemPropertyVariables>
         <persistenceTarget>h2_test</persistenceTarget>
      </systemPropertyVariables>
   </configuration>
</plugin>

The corresponding persistence-h2_test.properties file can be placed in src/test/resources so that it will only be used for testing and not unnecessarily included and deployed with the war at runtime.

Going further

There are several ways to improve on this solution if needed. One such way is to use a more complex encoding for the names of the properties files, specifying not just the environment in which they are to be used, but also more information (such as the persistence provider).
The names of the properties files should now be: persistence-h2.properties, persistence-mysql.properties or, even more specific: persistence-dev_h2.properties, persistence-staging_mysql.properties, persistence-production_amazonRDS.properties.
The advantage of such a naming convention – and it is just a convention as nothing changes in the overall approach – is simply transparency. It now becomes much clearer what the configuration does only by looking at the names:

  • persistence-dev_h2.properties: the persistence provider for the dev environment is a lightweight, in-memory H2 database
  • persistence-staging_mysql.properties: the persistence provider for the staging environment is a mysql instance
  • persistence-production_amazon_rds.propertie: the persistence provider for the production environment is Amazon RDS

Conclusion

This article discusses a flexible solution for doing environment specific configuration in Spring. For a complete configuration using this method, check out REST

Reference: Project Configuration with Spring from our JCG partner Eugen Paraschiv at the baeldung blog.

Share and enjoy!
Post to Facebook Post to TwitterPost to Google+Post to Delicious Post to StumbleUponAdd to LinkedInAdd to DiggAdd to RedditSend via Mail
  • http://about.me/mranest Anestis Georgiadis

    Main problem with this type of configuration strategy is that environment configuration settings must be known and set at development time. Furthermore, changes to these settings (e.g. database user’s password) requires repackaging the application with updated .properties file.

    I’ve found great flexibility in setting up Spring with an integration environment profile, that facilitates the need for continuous integration, and using a property override configurer to replace configuration settings as needed per environment. The -D trick is used to define a well-known filesystem (i.e. not classpath) location where the properties file will be loaded from, if existing (i.e. -DconfigDir=X passed in JVM’s command line arguments, and the configurer trying to load the file form ${configDir}/app.properties)

  • Ramesh Kesavanarayanan

    I am trying to supply a runtime name of the file (my message queue.properties file differs for my different environment)

    But I am not able to set the $(hostname} with the name of my hostname for spring application context to load it dynamically.

    If you have pointers for the same that would be really helpful



© 2010-2012 Java Code Geeks. Licenced under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.