Spring Profiles | Part 6 – Spring Rest Advance :

What have we learned so far,

Part 1 – Spring Rest Advance : Input / Bean Validations
In this post, we discussed the steps to validate the input bean in Spring Rest.

Part 2 – Spring Rest Advance : Rest Documentation with Swagger 2
In this post, we discussed the steps to configure swagger to do the documentation for Spring Rest services

Part 3 – Spring Rest Advance : Spring Boot with H2 DB
In this post, we discussed the steps to configure and use H2 db in spring boot

Part 4 – Spring Rest Advance : Spring Rest Versioning
In this post we discussed the different ways to do the Rest versioning.

Part 5 – Asynchronous Spring Service With @Async And @EnableAsync
In this post we discussed the way to execute a code asynchronously 

How to use Profiles in Spring Boot?
What are Profiles in Spring?
 
Each application have different environment on which it runs and each environment have different configuration settings which application requires to run. Like an application might need below environment to run.

 

Development environment- Where the developer develops and test the code.
Test Environment – Where the Tester tests the code
UAT Environment- Where the end user tests the code before moving it to production
Production Environment – Where the actual end user uses the website

Each environment have their configuration settings like mail server on Dev, Test, UAT and production may vary as the developer don’t want to use the production or UAT mail server for his local development.

Profiles are bunch of environment specific properties which gets activated based on their profile names.

How to implement Profiles in Spring Boot?
Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments. Any @Component, @Configuration or @Bean can be marked with @Profile to limit when it is loaded.

Our example – We will write a controller which requirers the MailServer and the configuration for this mail server depends on the environment on which the application is running. Like Dev environment may have the mail server host as dev-host, production will have the mail host as prod-host and all.
Lets see how to use profile with Spring Boot
1. Profiles with property files placeholders
We make properties files for each environment and set the profile in the application accordingly, so it will pick the respective properties file. Don’t worry, we will see how to set it up.

application.properties – Hold the common properties across the environments

#Common Properties to all environment

#Current profile name
spring.profiles.active=prod

spring.application.name=Spring Profiles

onlyfullstack.message=This is the primary Application Property for ${spring.application.name}

application-dev.properties – Hold the properties related to dev environments

# Development Environment Settings

onlyfullstack.message= This is the property file for the ${spring.application.name} specific to Dev Environment

onlyfullstack.mail.server=dev-server
onlyfullstack.mail.username=dev-user
onlyfullstack.mail.password=dev-password

application-test.properties – Hold the properties related to test environments

# Test Environment Settings

onlyfullstack.message= This is the property file for the ${spring.application.name} specific to Test Environment

onlyfullstack.mail.server=test-server
onlyfullstack.mail.username=test-user
onlyfullstack.mail.password=test-password

application-prod.properties – Hold the properties related to production environments

# Production Environment Settings

onlyfullstack.message= This is the property file for the ${spring.application.name} specific to Production Environment

onlyfullstack.mail.server=prod-server
onlyfullstack.mail.username=prod-user
onlyfullstack.mail.password=prod-password

Lets write a bean to read these value based on the environment.
Here @ConfigurationProperties will append the onlyfullstack.mail as prefix to each variable name and try to find the property key in the properties file.

package com.onlyfullstack.springprofiles.model;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("onlyfullstack.mail")
public class MailSettings {

    private String server;
    private String username;
    private String password;

    public String getServer() {
        return server;
    }

    public void setServer(String server) {
        this.server = server;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "MailSettings{" +
                "server='" + server + ''' +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                '}';
    }
}

2. Profiles with Stereotype Annotations
We can use @Profile annotation with stereotype annotations(@Component / @Service / @Repository / @Bean / @Configuration). Lets use the @Profile annotation to create the ConfigServer object.

 
Lets write some code for this
ConfigServer
package com.onlyfullstack.springprofiles.service;

public interface ConfigServer {

    String setup();
}

DevConfigServer

package com.onlyfullstack.springprofiles.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Profile("dev")
@Service
public class DevConfigServer implements ConfigServer {

 @Override
 public String setup() {
  return "Calling Dev Copnfig Server";
 }
}

TestConfigServer

package com.onlyfullstack.springprofiles.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Profile("test")
@Service
public class TestConfigServer implements ConfigServer {

 @Override
 public String setup() {
  return "Calling Dev Test Server";
 }
}

ProdConfigServer

package com.onlyfullstack.springprofiles.service;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;

@Profile("prod")
@Service
public class ProdConfigServer implements ConfigServer {

 @Override
 public String setup() {
  return "Calling Prod Copnfig Server";
 }
}

ProfileController

package com.onlyfullstack.springprofiles.controller;

import com.onlyfullstack.springprofiles.model.FinalResponse;
import com.onlyfullstack.springprofiles.model.MailSettings;
import com.onlyfullstack.springprofiles.service.ConfigServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProfileController {

    @Autowired
    ConfigServer configServer;

    @Autowired
    MailSettings mailSettings;

    @GetMapping("/welcome")
    public FinalResponse getDataBaseConnectionDetails() {
        return new FinalResponse(configServer.setup(), mailSettings);
    }
}

Lets run our app and hit the below url and we can see that the MailSettings have all production related settings and Config Message is from Production Configuration.
http://localhost:8080/welcome

 
Screenshot2B2019 06 162Bat2B18.23.23

How to Activate Profile?
1. JVM System Parameter
The profile names can also be passed in via a JVM system parameter. The profile names passed as the parameter will be activated during application start-up:
-Dspring.profile.active=prod

2. Environment Variable
You can change the profile dynamically whole running the application by passing the –spring.profiles.active=prod to the mvn command as below:

java -jar spring-profiles-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod

3. Programmatically via WebApplicationInitializer interface
In web applications, WebApplicationInitializer can be used to configure the ServletContext programmatically.

It’s also a very handy location to set our active profiles programmatically:

@Configuration
public class MyWebApplicationInitializer 
implements WebApplicationInitializer {

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

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

4. Programmatically via ConfigurableEnvironment
You can also set profiles directly on the environment:

@Autowired
private ConfigurableEnvironment configEnv;

configEnv.setActiveProfiles("prod");

Source Code

Download source code of Spring Rest Advance Topics from below git repository :
spring-rest-advance-topics

Spring Rest Advanced Tutorial

https://www.onlyfullstack.com/spring-rest-advanced-tutorial/

Lets go to our next tutorial where we will discuss below point

7. Best practices for Spring Rest
– How To Do @Async in Spring Service
– What is the need of Asynchronous?
– How to use @Async and @EnableAsync in Spring Boot
Blog URL – Part 7 – Best practices for Spring Rest