Spring 3.1 profiles and Tomcat configuration
By defining system property spring.profiles.active Spring allows us to create different beans depending on active profile name using XML configuration or @Profile annotation. As we all know system properties can be used in Spring XML files and we will take advantage of that.
In this post I will show how to use Spring profiles to create one package for all environments and how to run it on Apache Tomcat.
Example architecture
I think the most common and wanted architecture is when applications deployed on dev, test and production differ only in used properties file containing configuration. WAR contains configuration for all environments and correct one is chosen during runtime. So it is the best if in application resources we have files like:
src main resources - config_dev.properties - config_production.properties ...
Configuring Spring property placeholder
In order to load properties files in Spring we use <context:property-placeholder />
or @PropertySource annotation. In my example I will follow XML configuration approach for loading properties file:
<?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:config_${spring.profiles.active}.properties' /> </beans>
Configuring Tomcat
Now its time to tell Tomcat which profile is active. There at least ways to do that:
- defining context param in web.xml – that breaks “one package for all environments” statement. I don’t recommend that
- defining system property -Dspring.profiles.active=your-active-profile
I believe that defining system property is much better approach. So how to define system property for Tomcat? Over the internet i could find a lot of advices like “modify catalina.sh” because you will not find any configuration file for doing stuff like that. Modifying catalina.sh is a dirty unmaintable solution. There is a better way to do that.
Just create file setenv.sh in Tomcat’s bin directory with content:
JAVA_OPTS='$JAVA_OPTS -Dspring.profiles.active=dev'
and it will be loaded automatically during running catalina.sh start or run.
Conclusion
Using Spring profiles we can create flexible applications that can be deployed in several environments. How is it different from Maven profiles approach? With Maven a person who was building application had to define in which environment it was supposed to run. With approach described above environment decides if its development, testing or production. Thanks to that we can use exactly the same WAR file and deploy it everywhere.
Reference: Spring 3.1 profiles and Tomcat configuration from our JCG partner Maciej Walkowiak at the Software Development Journey blog.