Main Tutorials

Spring Profiles example

spring-conditional

Spring @Profile allow developers to register beans by condition. For example, register beans based on what operating system (Windows, *nix) your application is running, or load a database properties file based on the application running in development, test, staging or production environment.

In this tutorial, we will show you a Spring @Profile application, which does the following stuff :

  1. Create two profiles – dev and live
  2. If profile “dev” is enabled, return a simple cache manager – ConcurrentMapCacheManager
  3. If profile “live” is enabled, return an advanced cache manager – EhCacheCacheManager
Note

  1. Spring has supported @Profile annotation since version 3.1
  2. @Profile is inside spring-context.jar

Tools used :

  1. Spring 4.1.4.RELEASE
  2. Ehcache 2.9.0
  3. JDK 1.7

1. Spring @Profile Examples

This @Profile annotation can be applied at class level or method level.

1.1 Normal Spring Configuration, enable caching, so that Spring will expect a cache manager at runtime.

AppConfig

package com.mkyong.test;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
@ComponentScan({ "com.mkyong.*" })
public class AppConfig {
}

1.2 A dev profile, which returns a simple cache manager concurrentMapCacheManager

CacheConfigDev.java

package com.mkyong.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("dev")
public class CacheConfigDev {

	private static final Logger log = LoggerFactory.getLogger(CacheConfigDev.class);
	
	@Bean
        public CacheManager concurrentMapCacheManager() {
		log.debug("Cache manager is concurrentMapCacheManager");
                return new ConcurrentMapCacheManager("movieFindCache");
        }
	
}

1.3 A live profile, which returns ehCacheCacheManager

CacheConfigLive.java

package com.mkyong.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.ClassPathResource;

@Configuration
@Profile("live")
public class CacheConfigLive {

	private static final Logger log = LoggerFactory.getLogger(CacheConfigDev.class);
	
	@Bean
	public CacheManager cacheManager() {
		log.debug("Cache manager is ehCacheCacheManager");
		return new EhCacheCacheManager(ehCacheCacheManager().getObject());
	}

	@Bean
	public EhCacheManagerFactoryBean ehCacheCacheManager() {
		EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
		cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
		cmfb.setShared(true);
		return cmfb;
	}
	
}

2. Enable @Profile

Few code snippets to show you how to enable a Spring profile.

2.1 For non-web application, you can enable a profile via the Spring context environment.

App.java

package com.mkyong.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

	public static void main(String[] args) {

	  AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
	  //Enable a "live" profile
	  context.getEnvironment().setActiveProfiles("live");
	  context.register(AppConfig.class);
	  context.refresh();
		
	  ((ConfigurableApplicationContext) context).close();

	}
}

Output


DEBUG com.mkyong.test.CacheConfigDev - Cache manager is ehCacheCacheManager

Or, via the system property like this

App.java

package com.mkyong.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.AbstractEnvironment;

public class App {

	public static void main(String[] args) {

	  //Enable a "dev" profile
	  System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev");
	  ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
		
	}
}

Output


DEBUG com.mkyong.test.CacheConfigDev - Cache manager is concurrentMapCacheManager

2.2 For web application, defined a context parameter in web.xml

web.xml

	<context-param>
	    <param-name>spring.profiles.active</param-name>
	    <param-value>live</param-value>
	</context-param>

2.3 For web application don’t have web.xml, like servlet 3.0+ container

MyWebInitializer.java

package com.mkyong.servlet3;
 
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
 
public class MyWebInitializer extends
	AbstractAnnotationConfigDispatcherServletInitializer {
 
	//...
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		super.onStartup(servletContext);
		servletContext.setInitParameter("spring.profiles.active", "live");
	}
 
}

2.4 For Unit Test, uses @ActiveProfiles

CacheManagerTest.java

package com.mkyong.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.cache.CacheManager;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { AppConfig.class })
@ActiveProfiles("dev")
public class CacheManagerTest {

	@Autowired
	private CacheManager cacheManager;
	
	@Test
	public void test_abc() {
		//...
	}
	
}

3. More…

3.1 Spring @Profile can apply at method level.

AppConfig.java

package com.mkyong.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableCaching
@ComponentScan({ "com.mkyong.*" })
public class AppConfig {

	private static final Logger log = LoggerFactory.getLogger(AppConfig.class);
	
	@Bean
	@Profile("dev")
        public CacheManager concurrentMapCacheManager() {
		log.debug("Cache manager is concurrentMapCacheManager");
                return new ConcurrentMapCacheManager("movieFindCache");
        }
	
	@Bean
	@Profile("live")
	public CacheManager cacheManager() {
		log.debug("Cache manager is ehCacheCacheManager");
		return new EhCacheCacheManager(ehCacheCacheManager().getObject());
	}

	@Bean
	@Profile("live")
	public EhCacheManagerFactoryBean ehCacheCacheManager() {
		EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
		cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
		cmfb.setShared(true);
		return cmfb;
	}
	
}

3.2 You can enable multiple profiles.


	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
	context.getEnvironment().setActiveProfiles("live", "linux");
	//or
	System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "dev, windows");
web.xml

	<context-param>
	    <param-name>spring.profiles.active</param-name>
	    <param-value>stage, postgresql</param-value>
	</context-param>

	@ActiveProfiles({"dev", "mysql","integration"})

        ((ConfigurableEnvironment)context.getEnvironment())
                   .setActiveProfiles(new String[]{"dev", "embedded"});

Download Source Code

Download It – Spring-Profiles-Example.zip (17 KB)

References

  1. Spring Profiles – Environment Abstraction
  2. Spring Caching And Ehcache Example
  3. Spring MVC – Set active profile

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
13 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Ed Randall
6 years ago

Is it possible to select based on some expression of active profiles
eg. @Profile(“!dev”)

Krishna Gangaraju
7 years ago

for all options above we need to change code right ? enabling correct profile
if it is non-web application have to change in Main Class , if it is web application have to change it in web.xml (before pushing code to that particular environment

Jeremy Foster
7 years ago

For what it’s worth now or for those just seeing these comments you can set Environment variables in your system for the profiles you want active in that environment and then call something like the following depending on your system and code: System.getenv(“SPRING_PROFILES_ACTIVE”)

I have only just found so I am no expert but it saves you from having to constantly change the code.

Paul
8 years ago

One more way to set active profile:

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

public class Initilizer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getEnvironment().setDefaultProfiles(environmentType);
}
}

In this case you will avoid context refreshing, which is not always a good idea (especially, using spring-integration)

shruthi
8 years ago

can @Profile annotation accept more than one value? perhaps like @Profile({“dev”,”gamma”})

mkyong
8 years ago
Reply to  shruthi

Yes, review the Spring source code, @Profile accept String[].

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
String[] value();
}

ByteFlinger
9 years ago

“The annotation @Profile is disallowed for this location”

I get this is I try to use @Profile on a @Bean level. This must be a Spring 4 feature or something like that as I am using Spring 3.2.9 which as of right now is the latest

Lucky
7 years ago
Reply to  ByteFlinger

@Profile annotation are for method and class level only right?

Avec
5 years ago
Reply to  Lucky

@Profile annotation is valid together with @Component or @Configuration ref
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

mkyong
8 years ago
Reply to  ByteFlinger

Not sure about this, Spring @Profile has been available since Spring 3.

Brahmaiah R
9 years ago

good one… 🙂

Chris Nikitas
9 years ago

Perfect example, simple and to the point!

Exactly what I needed. Thanks a lot!!!

iqiwypy
5 years ago

Jestem fanem Sculpting Miniatures Trzebnica poczta kwiatowa