In this Spring boot tutorial, we will learn Spring profiles, @Profile annotation, profile specific beans, property files and configurations, profile groups and activating a particular profile in application startup.

1. Spring Profiles

1.1. What is a Profile?

In general, a profile is a segregation between different runtime environments in which the Spring application can run. For example, an application can run locally, in a development or test environment as well as in production. It is not easy to replicate the same hardware and software setup in all the above deployment environments. So the expectation is to configure the application in such a way that it must behave correctly in all these environments.

Interestingly, a profile is not limited to only deployment environments. It can be any type of segregation. For example, an application can connect to MySQL database in one profile while it will connect to H2 database in another profile. So here we have database configuration specific profiles. Similarly, profiles can be segregated on any basis.

So, in simple words, the purpose of spring profiles is to activate different beans in different environments at bootstrap time. Under the hood, a profile can control only two things:

  • which beans are loaded into the application context
  • which application properties are applied

1.2. What is Default Profile?

Before going further deep into the concept, it is crucial to understand that if we do not specify any profile explicitly, then the default profile is activated automatically.

When using the default profile, all such beans will be initialized that do not belong to any specific profile. All profile specific beans will be skipped from initialization.

It is equivalent to using the @Profile("default") annotation on all beans that do not belong to any specific profile.

The name of the default profile can be tuned using the spring.profiles.default property, as shown in the following example. This will change the name of default profile from default to none.

spring.profiles.default=none

2. @Profile Annotation

2.1. Using @Profile

The @Profile is used inside one of following annotated classes:

For example, if we have three profiles local, dev and prod then we can use following three classes to define profile specific beans.

@Profile("local")
@Configuration
public class LocalProfileConfiguration {

   @Bean
   public DataSource h2DataSource() {/*...*/}
}
@Profile("dev")
@Configuration
public class DevelopmentProfileConfiguration {

   @Bean
   public DataSource mySqlDataSource() {/*...*/}
}
@Profile("prod")
@Configuration
public class ProductionProfileConfiguration {

   @Bean
   public DataSource oracleDataSource() {/*...*/}
}

Similarly, we can apply the @Profile annotation with stereotype annotations as well.

Note that profile names can also be prefixed with a NOT operator. The !prod name configures the beans in all non-production environments.

@Profile("!prod")
@Configuration
public class NonProductionProfileConfiguration {

   @Bean
   public DataSource h2DataSource() {/*...*/}
}

2.2. Not a Best Practice

Though @Profile is an extremely useful and simple concept, still it has one significant disadvantage. It spreads the profile specific configurations in the source code in multiple places. And it makes it difficult to keep track of profile specific configurations over time.

Another problem is activating multiple profiles can result in duplicate beans and runtime exceptions. For example, suppose we have H2 DataSource bean definition in two different profiles inMemoryDataSource and local.

@Profile("inMemoryDataSource")
@Configuration
public class DevelopmentProfileConfiguration {

   @Bean
   public DataSource datasource() {/*...*/}
}
@Profile("local")
@Configuration
public class ProductionProfileConfiguration {

   @Bean
   public DataSource datasource() {/*...*/}
}

If we decide to activate both, inMemoryDataSource and local, profiles in runtime then there will be two beans of same type and it will result in a runtime error.

So, having a properly segregated configuration and beans is difficult but of utmost importance, if we decide to use the @Profile annotation. It is always better to use application.properties files as a central place for controlling the profile specific configurations and properties.

3. Profile Specific Properties

3.1. Profile Specific Properties Files

Spring Boot allows grouping the configuration parameters for different environments into the different application.properties configuration files. Spring Boot will automatically pick up the right configuration file depending on the activated profile and load the configuration properties from that file.

Properties files have to be named in the format application-{profile}.properties. For example,

  • application.properties – contains properties applicable to all environments
  • application-local.properties – configure the application when local profile is activated
  • application-dev.properties – configure the application when dev profile is activated
  • application-prod.properties – configure the application when prod profile is activated

For example, if we have different databases in different environments then we can create separate properties files like following example:

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=password

3.2. Multiple Profiles in application.properties

It is also possible to specify all the profile specific configurations in only the application.properties file using the spring.config.activate.on-profile property as the separator to indicate the profile.

application.name=My Application

#--- local profile ---#
spring.config.activate.on-profile=local
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=

#--- dev profile ---#
spring.config.activate.on-profile=dev
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=root
spring.datasource.password=password

Note that we can not use spring.profiles.active in profile specific documents as well as along with spring.config.activate.on-profile property. The following is an invalid configuration.

# Valid usecase
spring.profiles.active=prod

# Invalid usecase
spring.config.activate.on-profile=prod
spring.profiles.active=dev

4. Profile Groups

Starting Spring boot 2.4, we can define profile groups as well. A profile group allows to group similar profiles together.

For example, if we have different profiles for production configurations such as prodJms, prodDatabase, prodJndi etc., and we want to activate all these profiles while deploying the application in the production. To do so we can group all these profiles under a single profile name.

spring.profiles.group.prod=prodJms,prodDatabase,prodJndi

With above profile group definition, activating the prod profile will activate prodJms, prodDatabase and prodJndi as well.

5. Activating a Profile

The spring.profiles.active is a standard property that Spring Boot will pick up automatically to activate a profile. Pass the profile name to this property value to activate that profile.

If we want to activate multiple profiles then we can pass comma-separated names of those profiles.

We can set it in many places, for example, in application.properties file:

spring.profiles.active=dev

As JVM startup argument:

$ java -jar app.jar -Dspring.profiles.active=dev

As environment variable:

export spring_profiles_active=dev

While configuring WebApplicationInitializer:

@Configuration
public class CustomWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        servletContext.setInitParameter("spring.profiles.active", "dev");
    }
}

6. Conclusion

In this Spring boot tutorial, we learned about the profiles that help in segregating the configurations and properties specific to different deployment environments, but not limited to this.

We learned to create profile specific configurations and beans. We learned to activate a specific profile in runtime and profile groups.

Happy Learning !!

Sourcecode on Github

Was this post helpful?

Join 8000+ Awesome Developers, Like YOU!

Leave a Comment

About HowToDoInJava

This blog provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions, and frequently asked interview questions.