Understanding Profiles in Microservices

Hacker using computer, smartphone and coding to steal password and private data. Screen with code
Reading Time: 4 minutes

In this blog, we will learn and try to build an Understanding of Spring Profiles in Microservices. I’ll answer a few questions: what are profiles and why do we need them?

Your application is running, at the initial stages, it will run on the dev environment. After some time it will be running in a test environment and finally, it will be in production. So you want to have different configurations for the dev, test, and production environments. The question is how do we do that without even changing or touching the code?

Also, Spring Profiles play an important role in such requirements. Let’s move ahead and understand what are profiles and how do we use them?

What is Profile?

Spring has this feature called Profiles which you can leverage in order to have different values for the configuration in different environments. Profiles also provide a way to segregate parts of your application configuration like which configurations should be in the dev, test, and production environment. Any @Component or @Configuration can be marked with @Profile to limit when it is loaded. There are different beans and classes which we want to load in certain conditions and environments. For doing so, we can annotate it using @Profile and mention the profile for which the classes and beans are

Example:

@Configuration(proxyBeanMethods = false)
@Profile("production")
puclic class ProductionDetails {
               //
}

Here “production” is the name of the profile.

Likewise, we can specify for dev and test environment.

In properties or YAML files, we give spring.profiles.active=dev,hsqldb to add the profiles which are active. We can give more than one profile at the same time. Profiles are maintained in yaml or properties file.

Adding Active Profiles

You can use this property spring.profiles.active in the properties file and add the profile which is active. Active profile can be added by using SpringApplication.setAdditionalProfiles(…) also. The third way is using the command line, active profiles can be changed from the command line also.

Let’s See a Sample Project

Step 1

Go to the Spring initializer to create a spring boot project as mentioned below. Select the configurations accordingly.

Step 2

Create YAML file: You will have to create four YAML files, first create application.yaml file, and similarly the other three yaml files.

  • application.yaml file
  • application-dev.yaml
  • application-test.yaml
  • application-prod.yaml

In the application.yaml file, the property spring.profiles.active is used and you can specify the active profile there accordingly. Whichever profile is mentioned in the application.yaml file, it will pick up that profile’s configurations from its YAML file. You can add your profile-specific details in the data source property of each YAML file.

application.yaml
server:
  port: 8083

app:
  server:
    name: profiles
    detail: this is general server

spring:
  profiles:
    active:
      - dev
  datasource:
    url: jdbc:hsqldb:hsql://localhost/profiles
    username: profiles-user
    password: 12345
  application:
    name: This is a demo application for understanding profiles in microservices

application-dev.yaml
app:
  server:
    name: tomcat
    detail: this is tomcat for dev environment

spring:
  datasource:
    url: jdbc:hsql:hsql://localhost/devenv
    username: dev
    password: dev-en

application-test.yaml
app:
  server:
    name: jboss
    detail: this is jboss for test

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/testenv
    username: mysql
    password: test-en

application-prod.yaml
app:
  server:
    name: GlassFish
    detail: this is GlassFish for production environment

spring:
  datasource:
    url: jdbc:oracle:thin:@hostname:80:prodenv
    username: oracle-prod
    password: prod-en

Step 3

Create AppConfig class. As you can see in the below code, a bean named “environmentDetails” will hold all the profile-specific details present in the EnvironmentDetails.class.

AppConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
public class AppConfig {

    @Autowired
    private EnvironmentDetails environmentDetails;

    @Bean
    @Profile("dev")
    public EnvironmentDetails devEnv() {
        System.out.println("Dev Environment is Active.");
        System.out.println(environmentDetails.toString());
        return environmentDetails;
    }

    @Bean
    @Profile("test")
    public EnvironmentDetails testEnv() {
        System.out.println("Test Environment is Active.");
        System.out.println(environmentDetails.toString());
        return environmentDetails;
    }

    @Bean
    @Profile("prod")
    public EnvironmentDetails prodEnv() {
        System.out.println("Prod Environment is Active.");
        System.out.println(environmentDetails.toString());
        return environmentDetails;
    }
}

Step 4

Create an Environment details class. This class will be annotated using @Component annotation. This class will hold all the values which are present in the YAML files. What values will the below-mentioned fields i.e appServerName, appServerDetail, etc will depend on the App Config class and which profile is specified as the active profile in the application.yaml. If you mention “dev” as an active profile, it will pick up details of application-dev.yaml file and likewise for test and prod environments too. You can choose the environment accordingly.

EnvironmentDetails.java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class EnvironmentDetails {
    @Value("${app.server.name}")
    private String appServerName;
    @Value("${app.server.detail}")
    private String appServerDetail;
    @Value("${spring.datasource.url}")
    private String dbUrl;
    @Value("${spring.datasource.username}")
    private String dbUser;
    @Value("${spring.datasource.password}")
    private String dbPassword;

    public EnvironmentDetails() {

        System.out.println("");
    }

    public String getAppServerName() {
        return appServerName;
    }

    public void setAppServerName(String appServerName) {
        this.appServerName = appServerName;
    }

    public String getAppServerDetail() {
        return appServerDetail;
    }

    public void setAppServerDetail(String appServerDetail) {
        this.appServerDetail = appServerDetail;
    }

    public String getDbUrl() {
        return dbUrl;
    }

    public void setDbUrl(String dbUrl) {
        this.dbUrl = dbUrl;
    }

    public String getDbUser() {
        return dbUser;
    }

    public void setDbUser(String dbUser) {
        this.dbUser = dbUser;
    }

    public String getDbPassword() {
        return dbPassword;
    }

    public void setDbPassword(String dbPassword) {
        this.dbPassword = dbPassword;
    }

    @Override
    public String toString() {
        return "EnvironmentDetails{" +
                "appServerName = " + appServerName + "\n," +
                "appServerDetail = " + appServerDetail + "\n," +
                "dbUrl = " + dbUrl + "\n," +
                "dbUser = " + dbUser + "\n," +
                "dbPassword = " + dbPassword + "\n," +
                '}';
    }
}

Result of Using “dev” as Profile in the application.yaml

Let’s set the profile as “dev” in the application.yaml file and run the application:

spring:
  profiles:
    active:
      - dev

Output:

We are getting all the environment details we specified for den environment in application-dev.yaml file. Similarly, we can do the same for test and prod environments.

Conclusion

By defining YAML files for each environment, we can easily choose the environment we want to work in. This easily segregates the dev, test, and prod environments, and hence one can easily set the required configuration by simply specifying the active profile as dev, prod, and test.

Are you interested in reading more tech blogs? Please visit Knoldus’s blogs.

Written by 

Sakshi Mittal is a Software Consultant at Knoldus Software. She has completed her MCA from BCIIT and Bachelors in Computer Applications from GGSIPU. Her practice area is Java but she loves to explore machine learning field as well. She likes writing tech blogs and contribute to open source. When not working you will find her watching travel and food vlogs.

Leave a Reply