You are here
Home > java >

Profiles In Spring Boot

Profiles In Spring BootWhen we work on a real time project, we maintain multiple environment for the same project. This happens because we use different infrastructures for different stages of the project. There are different useful environments that we maintain before making the project go live, such as: development (DEV), test, user acceptance testing (UAT), production (PROD). These environments are not fixed at all. Some projects may have some more environments or even sometimes less also. It totally depends on the decisions made by stakeholders involved in the specific project and its requirements.

Spring Framework offers us to maintain a separate profile for each environment in order to switch over the environments with a minimal effort. Hence, our topic of discussion is โ€˜Profiles In Spring Bootโ€™.

For example, if we think about database URL, it will always be different in different environments. Moreover, it also allows us to map our beans to different profiles. Also, we can have control over the beans in such a way that a particular bean to bootstrap only when a particular profile is active. Similarly, some other configuration settings are environment specific that we will discuss in detail in the subsequent sections. Letโ€™s discuss our topic โ€˜Profiles In Spring Bootโ€™ and its related concepts step by step.

Please note that this article covers the details ofย  Profiles in Spring Boot and Spring framework both. We have clearly explained the additional features of Profiles In Spring Boot in a separate section.

What is Spring Profile?

Profiles are the group of configuration properties. These configuration properties belong to a specific environment. If all the configuration properties belong to development environment, we can call it development profile. Similarly, based on the specific configuration properties it holds, we can call other profiles as test profile, prod profile etc. Spring profiles provide a way to separate out parts of our application configuration and make it be available only in the specific environment/(s).

Programmatically, a profile is a property file with extension โ€˜.propertiesโ€™ similar to โ€˜application.propertiesโ€™ file. In spring Boot, apart from โ€˜.propertiesโ€™, a profile can also have โ€˜.ymlโ€™ extension.

What are the usages of Profiles in Spring Based Application?

Typically, Profiles control two things in a spring based application: configuration properties, and beans.

1) Configuration Properties: Profile controls which configuration properties should be active.

2) Beans: Profile controls which beans should be loaded into the Spring Container. It offers a provision to register beans by condition.

What is the Default Profile?

Spring Boot comes with a property file, named โ€˜application.propertiesโ€™ file by default. Therefore, this file is the default profile. Similarly, โ€˜application.ymlโ€™ file will also be the default profile. The default profile is always active. Spring Boot loads all properties from the default profile first.

If a property is defined in theย default profile, but not in the prodย profile, the property value will be populated from theย default profile. This is very handy for defining default values that are valid across all profiles. Hence, we should keep all properties in default profile (application. properties) which are common across all profiles.

How to create a Spring Profile?

Instead of changing multiple entries in the default profile each time, we will create a separate dedicated file for each environment. Further, we can activate the required profile by changing only a single entry in the default profile.

As aforementioned, Spring Profile contains the configuration properties of a particular environment. Therefore, we need to know how many environments we have in place. Suppose we have three environments such as: development, test, and production. In this case, we need to create three profiles.

Spring Boot comes with a property file, named โ€˜application.propertiesโ€™ file by default. Letโ€™s create three more property files at the same location where โ€˜application.propertiesโ€™ file resides as below.

1) application-dev.properties

2) application-test.properties

3) application-prod.properties

Please note the naming convention: application-<environment>.properties

Now, letโ€™s insert some configuration properties in these files. For example, letโ€™s insert database configurations which are different in each file. Assume that h2 DB in development, MySQL in test, and Oracle DB in production. We will update the entries as shown below:

application-dev.properties

app.info= This is the DEV Environment Property file
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db
spring.datasource.userName=sa
spring.datasource.password=sa

application-test.properties

app.info= This is the TEST Environment property file
spring.datasource.url=jdbc:mysql://localhost:3306/myTestDB
spring.datasource.username=root
spring.datasource.password=root123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

application-prod.properties

app.message = This is the PROD Environment property file
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username=username
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
If we donโ€™t implement profiles, we will have to accommodate all the above entries in a single file โ€˜application.propertiesโ€™. Further, if we want to switch over to different profile, we will have to make many changes every time. Hence, maintaining a separate profile for each environment saves a lot of effort.

How to Activate a Particular Profile?ย 

Although, we have multiple ways to make a particular profile active. Letโ€™s discuss some of them one by one.

Approach#1: By setting โ€˜spring.profile.activeโ€™ in application.properties

The โ€˜application.propertiesโ€™ file will be the boss among all the properties files. Here we will specify which profile is active by setting the value of property โ€˜spring.profiles.activeโ€™. For example, below โ€˜application.propertiesโ€™ file represents that currently โ€˜development (dev)โ€™ profile is active.

***โ€”application.propertiesโ€”***

spring.application.name = Spring Profiles
spring.profiles.active = dev
app.info = This is the Primary Application Property file
In the preceding code, the value ofย  โ€˜spring.profiles.activeโ€™ property tells Spring which profile to use. Here we have set the dev profile as active.

This is the most commonly used approach of making a particular profile active.

Approach#2: By setting in JVM System Parameter

We can also pass the profile name in a JVM System parameter as below. The specified profile will be activated during application startup.

-Dspring.profiles.active=dev

Approach#3: By setting context parameter in web.xml

If you have web.xml in a web application, spring active profile can be set by specifying a context parameter as shown below:

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

Approach#4: By implementing WebApplicationInitializerย Interface

Programmatically, in web applications, we can configure the ServletContext by implementing WebApplicationInitializer interface. Here, we can also set our active profiles programmatically as shown below:

@Configuration
public class MyWebApplicationInitializer implements WebApplicationInitializer {

   @Override
   public void onStartup(ServletContext servletContext) throws ServletException {
      servletContext.setInitParameter( "spring.profiles.active", "dev"); 
   } 
}

Approach#5: By setting active profiles in pom.xml

Furthermore, we can activate spring profile via Maven profiles by specifying the โ€˜spring.profile.activeโ€™ property as shown below.

<profiles>
  <profile>
     <id>dev</id>
     <activation> <activeByDefault>true</activeByDefault> </activation>
     <properties> <spring.profiles.active>dev</spring.profiles.active> </properties>
  </profile>
  <profile>
     <id>test</id>
     <properties> <spring.profiles.active>test</spring.profiles.active> </properties>
  </profile>
</profiles>

Priority on Using Multiple Approaches

Suppose we have used multiple approaches to set active profile in the same project, then Spring will prioritize approaches in below order.

1) By Setting a context parameter in web.xml

2) By Implementing WebApplicationInitializer Interface

3) By Setting JVM System Parameter

4) By Setting active profiles on pom.xml

How to specify all Profiles in the same application.properties file?

Instead of defining separate profiles for each environment, we can even combine all the properties in the same file and use a separator to indicate the profile. This has become possible since Spring Boot 2.4. Spring Boot has extended its support for multi-document files for properties files. This feature was already available in a YAML file. Therefore, we can specify theย dev, test,ย andย production properties in the same application.properties file as shown below:

app.info= This is the multi-document file
spring.config.activate.on-profile=dev
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db
spring.datasource.userName=sa
spring.datasource.password=sa

# ---

spring.config.activate.on-profile=test
spring.datasource.url=jdbc:mysql://localhost:3306/myTestDB
spring.datasource.username=root
spring.datasource.password=root123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

# ---

spring.config.activate.on-profile=prod 
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:xe 
spring.datasource.username=username 
spring.datasource.password=password 
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true 
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver 
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect

How does Spring Container read multi-document file?

Spring Container reads this file from top to bottom order. That is, if some property, say โ€˜spring.datasource.urlโ€™, occurs more than once in the file, the container will consider the endmost value. In the above example, based on the endmost value, it is clear that the prod profile is active as the value of property โ€˜spring.config.activate.on-profileโ€™ is set to โ€˜prodโ€™.

Note: One point to note here is that starting Spring Boot 2.4, property โ€˜spring.config.activate.on-profileโ€™ canโ€™t be used in combination with propertyย  โ€˜spring.profiles.activeโ€™. On doing so, we can see a ConfigDataException.

How To Use @Profile Annotation?

By using @Profile annotation, we can make a bean belong to a particular profile. The @Profile annotation simply takes the names of one or multiple profiles. In simple words, @Profile annotation associates a bean to a particular profile. For example, letโ€™s consider a scenario: We need a bean that should only be active during development, but not production. It will only be present in the container during development. In production, it wonโ€™t be active. Below code demonstrates the concept:

@Profile("dev") 
@Component 
public class MyBeanConfig{...}

Furthermore, profile names can also be prefixed with a NOT operator, e.g., !dev, to exclude them from a profile.ย For example, the below component is activated only if devย profile is not active:

@Profile("!dev") 
@Component 
public class MyBeanConfig {...}

Moreover, we can also associate a bean with a particular profile via XML configuration.ย The <beans> tag has a profile attribute to specify active profiles for that bean as shown below:

<beans profile="dev">
    <bean id="myBeanConfig" 
      class="com.dev.profiles.MyBeanConfig"/>
</beans>

Furthermore, We can also activate multiple profiles at a time by using @Profile annotation as shown below:

@Configuration 
public class AppConfig { 

  @Profile({"prod", "dev"}) 
  @Bean 
  public MyBean getBean() {
    return new MyBean(); 
  } 
}

How to work with profiles using .yml?

Profiles in Spring Boot also offers to work with YAML(.yml) files. As an alternative to application.properties file, we can create application.yml file as a default profile. Like application.properties file, when application.yml file exists in the project, Spring Container will load it automatically on application startup. Further, similar to .properties file, we can create multiple profiles following the naming convention (application-<environment>.yml). However, we also have second approach to create multiple profiles in the same file using .yml. Here, we will talk about both approaches in detail step by step.

Approach#1: By Creating Separate files for each Profile

Letโ€™s create application.yml and three profiles for development, test & production environment respectively.

application.yml

spring:  
  profiles:  ย  
    active: dev
  application:
  name: This is default profile
app: 
  name: This is the Primary Application yml file

application-dev.yml

spring: 
  profiles: dev 
  datasource: 
    username: sa 
    password: sa 
    url: jdbc:h2:mem:db 
    driver-class-name: org.h2.Driver

application-test.ymlย 

spring: 
  profiles: test 
  datasource: 
    username: root
    password: root123
    url: jdbc:mysql://localhost:3306/myTestDB 
    driver-class-name: com.mysql.cj.jdbc.Driver

application-prod.yml

spring: 
profiles: prod
  datasource: 
    username: username1
    password: password@123
    url: jdbc:oracle:thin:@localhost:1521:xe
    driver-class-name: oracle.jdbc.OracleDriver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.Oracle10gDialect

Approach#2: By Creating Single file for all Profiles

Create an application.yml and accommodate all the profiles in it. The first property โ€˜spring.profiles.activeโ€™ represents the active profile. Three hyphens work as a profile separator in this file. Hence, after completion of one profile insert three hyphens as shown below.

spring:
  profiles:
  ย  active: dev
---
spring:
 profiles: dev
 datasource: 
   username: sa
   password: sa
   url: jdbc:h2:mem:db
   driver-class-name: org.h2.Driver
---
spring: 
  profiles: test 
  datasource: 
    username: root
    password: root123
    url: jdbc:mysql://localhost:3306/myTestDB 
    driver-class-name: com.mysql.cj.jdbc.Driver
---
spring: 
  profiles: prod
  datasource: 
    username: username1
    password: password@123
    url: jdbc:oracle:thin:@localhost:1521:xe
    driver-class-name: oracle.jdbc.OracleDriver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    properties:
      hibernate:
        dialect: org.hibernate.dialect.Oracle10gDialect  
---    

As shown in the above example, from the first property, it is clear that โ€˜devโ€™ profile is active. Additionally, this single file accommodates all the profiles in it.

Profiles In Spring Boot

This section is dedicated to Profiles In Spring Boot, especially about the new features introduced in Spring Boot 2.4.

Starting Spring Boot 2.4, there are multiple changes came into the picture in the context of Profiles In Spring Boot. Letโ€™s summarize them one by one.

1) Activation of a Specific Profile: Apart from property โ€˜spring.profiles.activeโ€˜, a new property โ€˜spring.config.activate.on-profileโ€™ can be used to set/activate a specific profile. However, we canโ€™t use them together otherwise we may see ConfigDataException.

2) To activate Profiles In Spring Boot programmatically, we can also use the SpringApplication class(main class of the application) as below:

SpringApplication.setAdditionalProfiles("test");

3) In order to activate a profile in Spring Boot using pom.xml, we can specify profile names under โ€˜spring-boot-maven-pluginโ€™ as below:

<plugins> 
  <plugin>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-maven-plugin</artifactId> 
        <configuration> 
           <profiles> 
             <profile>test</profile>
           </profiles>
        </configuration> 
  </plugin> 
  ... 
</plugins>

4) Spring Boot 2.4 has also introduced a feature called โ€˜Profile Groupsโ€™. Using this feature of Profiles In Spring Boot 2.4, we can group similar profiles in spring boot together. Suppose we have multiple profiles for development environment. Letโ€™s say a โ€˜devdbโ€™ for the database configuration, and โ€˜devemailโ€™ for the email configuration. In order to activate these profiles together via โ€˜application.propertiesโ€™, we can do it as shown below.

spring.profiles.group.production=devdb,devemail

As a result, once we activate the development profile, it will activate โ€˜devdbโ€™ and โ€˜devemailโ€™ as well.

5) As aforementioned, we can even combine all the properties of multiple profiles in a single file โ€˜application.propertiesโ€™ and use a separator to indicate the profile. This feature was already existing in case of YAML(application.yml) file before Spring Boot 2.4 as well.

How to check which Profile is currently Active?

We have discussed at length about creating and activating profiles in Spring Boot. Now, its time to find out how we can check which profile is currently active. Typically, there are two ways to do it. Letโ€™s discuss them one by one.

Approach#1: Using Environment Object

We can use Javaโ€™s Environment object as a bean via auto-wiring to get the active profile as shown below:

import org.springframework.core.env;

public class ProfileController {
   
   @Autowired ย ย ย 
   private Environment env; 
ย ย  
   public void getActiveProfiles() { ย ย ย ย ย ย 
    ย  for (String profile : env.getActiveProfiles()) { 
ย ย ย ย ย ย ย ย ย ย ย ย System.out.println("Current active profile: " + profile); ย ย ย ย ย ย ย  
      }ย ย  ย ย ย ย 
   } 
}

Approach#2: By injecting the property โ€˜spring.profiles.activeโ€™

Letโ€™s observe the below code:

public class ProfileController { 

   @Value("${spring.profiles.active:}")
   private String activeProfiles; 

   public String getActiveProfiles() {
      for (String profile : activeProfiles.split(",")) {
         System.out.println("Current active profile: " + profile);
      } 
   } 
}

As shown in the code above, activeProfiles variable will hold the name of the profile that is currently active, and if there are multiple, it will contain their names separated by a comma.

For more Spring Core and Spring Boot Tutorials, kindly visit Spring Boot Tutorial section.

3 thoughts on โ€œProfiles In Spring Bootโ€

Leave a Reply


Top