Home  >  Spring Boot

Spring Boot Profiles Example

By Arvind Rai, March 29, 2017
This page will walk through spring boot profiles example. Spring provides @Profile annotation using which we create profiles. @Profile is used with @Configuration and spring stereotypes such as @Component, @Service etc. Different profile is created for different environment. For example we can have environment such as production, development and testing. In development environment we can enable development profile and in production environment we can enable production profile and so on. A profile can be activated using property file .properties/.yml, command line and programmatically. We can also create a default profile that will work when there is no active profile. To add active profile in property file, we need to configure spring.profiles.active property. We can also configure profile using spring.profiles.include that will be included for every active profile. When we add active profile using command line then the active profile added in property file is replaced. We can add active and default profile programmatically by using ConfigurableEnvironment. In spring boot testing we can add active profile by using @ActiveProfiles annotation. We can create property file using profile name using the convention application-{profile}.properties. The advantage of this approach is that we can configure properties profile specific. Now find the complete spring boot profiles example step by step.

Create Spring Profiles

In our example we will create profiles for two environments i.e. development and production. Profile is declared as @Profile("profile-name") annotated at class level. We are creating four profiles that are dev, prod, animal_dev and animal_prod. In our example we are creating two components that will configure server port and context path and we will have two service classes.
Find the component that will configure server port and context path for production environment.
ProdCustomizer.java
package com.concretepage.config;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile("prod")
public class ProdCustomizer implements EmbeddedServletContainerCustomizer {
	@Override
	public void customize(ConfigurableEmbeddedServletContainer container) {
		container.setContextPath("/spring-boot-prod");
		container.setPort(8585);
	}
}  
Find the component that will configure server port and context path for development environment.
DevCustomizer.java
package com.concretepage.config;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Component
@Profile("dev")
public class DevCustomizer implements EmbeddedServletContainerCustomizer {
	@Override
	public void customize(ConfigurableEmbeddedServletContainer container) {
		container.setContextPath("/spring-boot-dev");
		container.setPort(8484);
	}
}  
We are also creating services for prod and dev environments.
Animal.java
package com.concretepage.service;
public interface Animal {
	String getMessage();
} 
Elephant.java
package com.concretepage.service;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
@Service
@Profile("animal_dev")
public class Elephant implements Animal {
	@Override
	public String getMessage() {
		return "Hello Elephant!";
	}

} 
Lion.java
package com.concretepage.service;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
@Service
@Profile("animal_prod")
public class Lion implements Animal {
	@Override
	public String getMessage() {
		return "Hello Lion!";
	}
} 

Add Active Profile using Property File (.properties/.yml)

To add active profile, spring boot provides spring.profiles.active property. Suppose we want to enable dev and animal_dev profile, we can do as follows.
Using application.properties
spring.profiles.active=dev, animal_dev 
Using application.yml
spring:
  profiles:
    active:
     - dev
     - animal_dev 

Create Controller and Main Class

Our example is a web project in which we have a controller. Within the controller our service class will be autowired at run time on the basis of active profile.
HelloController.java
package com.concretepage.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.concretepage.service.Animal;
@RestController
public class HelloController {
   @Autowired
   private Animal animal;	
   @GetMapping("/")	
   public String getMessage() {
	   return animal.getMessage();
   }
} 
Run the demo using following class.
MyApplication.java
package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
	SpringApplication.run(MyApplication.class, args);
    }       
} 
Access the URL
http://localhost:8484/spring-boot-dev/ 
Find the output.
Hello Elephant! 

Add Active Profiles using Command Line

We can add active profiles using command line with java command. In this case active profile configured in property file will be replaced by active profile passed in command line. In our property file we have added active profile for dev environment. So by default application will start with dev environment. Now we will add prod active profile using command line. Suppose we have executable JAR named as spring-boot-demo-0.0.1-SNAPSHOT.jar. We will pass argument as -Dspring.profiles.active=animal_prod .
java -jar -Dspring.profiles.active="prod, animal_prod" spring-boot-demo-0.0.1-SNAPSHOT.jar 
For single profile we can use command as follows.
java -jar -Dspring.profiles.active=animal_prod spring-boot-demo-0.0.1-SNAPSHOT.jar 

Include Active Profiles

Spring boot can include a common set of profiles for every active profiles. We can configure spring.profiles.include property in our property file. Now whenever we add active profile using spring.profiles.active then by default profiles configured by spring.profiles.include will also be added. If we replace active profile by command line, still the profiles configured by spring.profiles.include will be added as active profile. We use it as follows.
Using application.properties
spring.profiles.active=dev
spring.profiles.include: animal_dev 
This will add two active profiles dev and animal_dev.
Now using application.yml
spring:
  profiles:
    active: dev
    include: animal_dev 
Using command line
java -jar -Dspring.profiles.active=prod spring-boot-demo-0.0.1-SNAPSHOT.jar 
The above command line will add two active profiles prod and animal_dev. animal_dev will be taken from property file.

Active Profile Unit Test using @ActiveProfiles

Now we will test our profile using unit test cases. We have created two test methods one for service classes and another for embedded server configuration customizer classes. To add active profile, spring test framework provides @ActiveProfiles annotation. Find the test class.
ActiveProfileTest.java
package com.concretepage;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
import com.concretepage.service.Animal;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
@ActiveProfiles({"prod","animal_prod"})
public class ActiveProfileTest {
        @Autowired
        private Animal animal;	
	@Autowired
	private TestRestTemplate restTemplate;
	@Test
	public void serviceTest() {
		String message = animal.getMessage();
		assertThat(message).isEqualTo("Hello Lion!");
	}
	@Test
	public void webAppTest() {
		String url = "http://localhost:8585/spring-boot-prod/";
		String body = this.restTemplate.getForObject(url, String.class);
		assertThat(body).isEqualTo("Hello Lion!");
	}
} 
@SpringBootTest: It is used to run test cases for spring boot based application. The test class will be annotated by @SpringBootTest annotation.
@ActiveProfiles: Spring test framework provides this annotation to use active profile in our test cases.
TestRestTemplate : Spring test framework provides TestRestTemplate to test spring boot based REST web service application. We can directly autowire this class in our test class. But it will work only when our test class has been annotated with @SpringBootTest using metadata webEnvironment=WebEnvironment.RANDOM_PORT.

Set Active Profiles Programmatically using SpringApplication.setAdditionalProfiles(...)

We can set active profiles programmatically using SpringApplication.setAdditionalProfiles(...) as follows.
MyApplication.java
package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
	SpringApplication application = new SpringApplication(MyApplication.class);
	application.setAdditionalProfiles("dev","animal_dev");
	application.run(args);
    }       
} 
We need to call setAdditionalProfiles() method before run() method. Here we have added active profiles dev and animal_dev.

Set Active Profiles Programmatically using ConfigurableEnvironment.setActiveProfiles(...)

We can set active profiles programmatically using ConfigurableEnvironment.setActiveProfiles(...).
MyApplication.java
package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
	SpringApplication application = new SpringApplication(MyApplication.class);
	ConfigurableEnvironment environment = new StandardEnvironment();
	environment.setActiveProfiles("dev","animal_dev");
	application.setEnvironment(environment);
	application.run(args);
    }       
} 
ConfigurableEnvironment provides facility to set active and default profiles. To set active profile, setActiveProfiles(...) method is used. ConfigurableEnvironment is an interface and there are many implementations of it. We are using here StandardEnvironment that is implementation class of ConfigurableEnvironment.

Set Default Profiles

There should be a default profile that should be loaded if no profile is enabled. We can set default profile that will be used by spring boot application when we have not configured any active profile.
We can set default profiles using setDefaultProfiles(...) method of ConfigurableEnvironment as follows.
MyApplication.java
package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.StandardEnvironment;
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
	SpringApplication application = new SpringApplication(MyApplication.class);
	ConfigurableEnvironment environment = new StandardEnvironment();
	environment.setDefaultProfiles("dev","animal_dev");
	application.setEnvironment(environment);
	application.run(args);
    }       
} 

Profile-Specific Property File

We can have property file specific to a profile with the convention application-{profile}.properties. In this way we can have separate property file for different environment. If we have added an active profile then only corresponding property file will be used by our spring boot application. We can also have a property file for default profile.
Suppose we have profiles as dev for development environment and prod for production environment. Then we can have profile specific properties as follows.
application-dev.properties
logging.level.org.springframework.web= DEBUG
logging.level.com.concretepage= DEBUG 
application-prod.properties
logging.level.org.springframework.web= ERROR
logging.level.com.concretepage= INFO

logging.path = concretepage/logs 
application-default.properties
logging.level.org.springframework.web= INFO
logging.level.com.concretepage= INFO 
Now if we add active profile dev as follows
application.properties
spring.profiles.active=dev, animal_dev 
Then application-dev.properties as well as application.properties will be used by our spring boot application.
If we add active profile prod as follows
application.properties
spring.profiles.active=prod, animal_prod 
Then application-prod.properties as well as application.properties will be used by our spring boot application.

If default profile is active then application-default.properties as well as application.properties will be used by our spring boot application.
Find the print screen.
Spring Boot Profiles Example

In the same way we can use .yml with the convention application-{profile}.yml. For the profiles dev and prod we can have .yml files as follows.
application-dev.yml
application-prod.yml
application-default.yml
application.yml

I am done now. Happy Spring Boot Learning!

Reference

Spring Boot Features:Profiles

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS


©2018 concretepage.com | Privacy Policy | Contact Us