Spring Environment Profiles
Often time our web applications depend on properties that can change depending upon the environment (DEV/Stage/Production) the application is running. Examples of these include admin email addresses or URLs to communicate with web services. I am a big advocate of promoting the same war file across all the environments. In order to achieve that, I create separate property files and bundle them in the war file. Couple years ago, I wrote a custom Properties Holder implementation that would look at a JNDI key “Environment” and load the appropriate property file. Spring 3.1 introduces Environment Profiles that simplifies this entire process.
In this blog, I will create a web application and three property files each holding an email address that is specific to an environment. Then I will create bean profile definitions in Spring context file and activate them external to the web application.
We start by creating a Maven based web application using my Spring archetype. Here is the generated web application:
The next step is to create the following three property files in the src->main->resources folder:
Now, let’s modify the applicationContext.xml file to include the bean profiles each loading their respective property files. Here is the modified application-Context.xml 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" xmlns:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd"> <!-- Load the dev property files by default --> <util:properties id="projectProperties" location="classpath:project_dev.properties"/> <beans profile="Test"> <util:properties id="projectProperties" location="classpath:project_test.properties"/> </beans> <beans profile="Prod"> <util:properties id="projectProperties" location="classpath:project_prod.properties"/> </beans> </beans>
Notice that we are using Spring’s new 3.1 schema definitions in the context file. The context file has two profiles one for test and one for production. By default, Spring would load all the properties from the project_dev.properties file. Also observe that we have used the same id for all the util:properties beans.
We then modify the HomeController class and home.jsp file to read and display the “admin.email” property. We do that using the @Value annotation in the HomeController and add it to Model as shown below:
package com.inflinx.blog.springprofiles.web.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/home.html") public class HomeController { @Value("#{projectProperties.adminEmail}") private String adminEmail; @RequestMapping(method = RequestMethod.GET) public String showHome(Model model) { model.addAttribute("adminEmail", adminEmail); return "home"; } }
Finally, we modify the home.jsp page to show the email property:
<%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
<%@ page session=”false” %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Admin Email: ${adminEmail}
</h1>
</body>
</html>
Deploy the application and you should see the default dev admin email in the browser:
To activate the Test profile, add the Environment Variable spring.profiles.active with value Test. In Windows, you can do that by going to Advanced Settings -> Environment Variable -> New
If you are running your Application Server from Eclipse, restart Eclipse and redeploy the app. In the logs you should be able to see that Spring has activated Test profile:
Upon refreshing the browser, you should see the new admin email: