Spring Profile XML Configuration

If you like to load environment specific spring configuration you can do this using profile. In other words, if you want to load a set of beans that have different settings on different environment (development, testing or production) you can use profile feature instead of pointing to a different spring xml configuration at each stage.

springsource

Objective:

  • How to use profile in spring xml configuration?

Environment & Tools:

  • Eclipse
  • Maven (optional)

Libraries:

  • Spring framework

Source Code @ GitHub

( 1 ) Two Spring XML Config (non-profile-way)

Assume we have two different spring xml configuration files and we want to load each one of them on a different environment “one for development and one for production”.

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

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

			<bean id="person" class="com.hmkcode.vo.Person">
				<property name="id" value="1" />
				<property name="name" value="dev-person" />
			</bean>
</beans>
  • 2. spring-config-production.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans   xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://www.springframework.org/schema/beans 

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

			<bean id="person" class="com.hmkcode.vo.Person">
				<property name="id" value="2" />
				<property name="name" value="pro-person" />
			</bean>
</beans>

One solution is to explicitly point to each one when we move from one environment to another.

  • On development
public class App 
{
    public static void main( String[] args )
    {

    	ClassPathXmlApplicationContext ctx = 
        new ClassPathXmlApplicationContext("spring-config-development.xml");
        Person person =  (Person)ctx.getBean("person");
        System.out.println("Person: "+person);
    }
}
  • On Production
public class App 
{
    public static void main( String[] args )
    {

    	ClassPathXmlApplicationContext ctx = 
        new ClassPathXmlApplicationContext("spring-config-production.xml");
        Person person =  (Person)ctx.getBean("person");
        System.out.println("Person: "+person);
    }
}

( 2 ) Using profile

Spring 3.1 has introduced “profile” the environment aware feature.

To use profile, we need to add profile property to <beans> in xml file.

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

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

		profile="development">

			<bean id="person" class="com.hmkcode.vo.Person">
				<property name="id" value="1" />
				<property name="name" value="dev-person" />
			</bean>
</beans>
  • 2. spring-config-production.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans   xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://www.springframework.org/schema/beans 

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

		profile="production">

			<bean id="person" class="com.hmkcode.vo.Person">
				<property name="id" value="2" />
				<property name="name" value="pro-person" />
			</bean>
</beans>

Now, in the main class we need to use GenericXmlApplicationContext since it allows us to point to more than one xml files. The question now is which xml to load? we can specify which xml to load by setting the active profile

  • either System.setProperty(“spring.profiles.active”, “development”);
  • or ctx.getEnvironment().setActiveProfiles(“development”);
package com.hmkcode;

import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import com.hmkcode.vo.Person;

public class App 
{
    public static void main( String[] args )
    {

    	System.setProperty("spring.profiles.active", "development"); //or production
    	GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();

    	ctx.load("spring-config-development.xml","spring-config-production.xml");

    	// Alternative way to set the active profile
    	//ctx.getEnvironment().setActiveProfiles("development"); //or production
    	ctx.refresh();

        Person person =  (Person)ctx.getBean("person");
        System.out.println("Person: "+person);
    }
}

One further enhancement is to combine all xml files into one file as following:

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

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

		<beans profile="development">
			<bean id="person" class="com.hmkcode.vo.Person">
				<property name="id" value="1" />
				<property name="name" value="dev-person" />
			</bean>
		</beans>

		<beans profile="production">
			<bean id="person" class="com.hmkcode.vo.Person">
				<property name="id" value="2" />
				<property name="name" value="pro-person" />
			</bean>
		</beans>
</beans>

Now, we can also change java code as following

package com.hmkcode;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.hmkcode.vo.Person;

public class App 
{
    public static void main( String[] args )
    {

    	System.setProperty("spring.profiles.active", "development"); //or production
    	ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config-all.xml");

        Person person =  (Person)ctx.getBean("person");
        System.out.println("Person: "+person);
    }
}