Spring Boot Profiles Example
December 01, 2023
Spring provides @Profile
annotation to create profiles that is used with @Configuration
and Spring stereotypes such as @Component
, @Service
etc. Different profiles are 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.
Contents
1. Create 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
@Component @Profile("prod") public class ProdCustomizer implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setContextPath("/spring-boot-prod"); container.setPort(8585); } }
DevCustomizer.java
@Component @Profile("dev") public class DevCustomizer implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.setContextPath("/spring-boot-dev"); container.setPort(8484); } }
Animal.java
public interface Animal { String getMessage(); }
@Service @Profile("animal_dev") public class Elephant implements Animal { @Override public String getMessage() { return "Hello Elephant!"; } }
@Service @Profile("animal_prod") public class Lion implements Animal { @Override public String getMessage() { return "Hello Lion!"; } }
2. Using (.properties/.yml)
To add active profile, Spring Boot providesspring.profiles.active
property. Suppose we want to enable dev and animal_dev profile, we can do as below.
Using
application.properties
spring.profiles.active=dev, animal_dev
application.yml
spring: profiles: active: - dev - animal_dev
3. 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
@RestController public class HelloController { @Autowired private Animal animal; @GetMapping("/") public String getMessage() { return animal.getMessage(); } }
MyApplication.java
@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
http://localhost:8484/spring-boot-dev/
Hello Elephant!
4. 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
Now using
application.yml
spring: profiles: active: dev include: animal_dev
java -jar -Dspring.profiles.active=prod spring-boot-demo-0.0.1-SNAPSHOT.jar
5. @ActiveProfiles with @SpringBootTest
We can 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
@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 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
.
6. Set Active Profiles Programmatically
1. Using SpringApplication.setAdditionalProfiles() :We can set active profiles programmatically using
setAdditionalProfiles()
as below.
MyApplication.java
@SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MyApplication.class); application.setAdditionalProfiles("dev","animal_dev"); application.run(args); } }
setAdditionalProfiles()
method before run()
method. Here we have added active profiles dev and animal_dev.
2. Using ConfigurableEnvironment.setActiveProfiles() : We can set active profiles programmatically using
setActiveProfiles()
method.
MyApplication.java
@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, its setActiveProfiles()
method is used. ConfigurableEnvironment
is an interface and there are many implementations of it.
7. 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
@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); } }
8. Profile-Specific Property File
We can have property file specific to a profile with the conventionapplication-{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 following.
application-dev.properties
logging.level.org.springframework.web= DEBUG logging.level.com.concretepage= DEBUG
logging.level.org.springframework.web= ERROR logging.level.com.concretepage= INFO logging.path = concretepage/logs
logging.level.org.springframework.web= INFO logging.level.com.concretepage= INFO
application.properties
spring.profiles.active=dev, animal_dev
application-dev.properties
as well as application.properties
will be used by our application.
If we add active profile as prod,
application.properties
spring.profiles.active=prod, animal_prod
application-prod.properties
as well as application.properties
will be used by our application.
If default profile is active then
application-default.properties
as well as application.properties
will be used by our application.
Find the print screen.
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 below.
application-dev.yml
application-prod.yml
application-default.yml
application.yml