Saturday, 4 May 2019

Explain @Profile Annotation in Spring 4

If you are working for a real time projects, it is often basic requirement to have the different environments like development, testing and production. In this scenario, the underlying resources (ie, database, file system, etc) for each environment would be different. The challenges arises when you want to move your source code to different environments. You would have to adjust the configurations to point to new environment details like Database, etc. The solution for the above problem is to create different profiles for each environment and enable them when you move to another environment.



@Profile annotation is introduced as part of the Spring Framework 3.1 release. @Profile annotation helps developers to create multiple configurations details for different environments. Prior to Spring 4, only bean level annotation is supported by @Profile. With Spring 4, this can be used in the method level. That gives more control and eliminate the need for creating multiple configuration files. This tutorial provide simple example for @Profile annotation.

Spring official document defines @Profile as:

Spring Profiles provide a way to segregate parts of your application configuration and make it only available in certain environments.

I have written a very simple example to demonstrate the power of @Profile feature in Spring 4. This example declares data source for dev and prod. By using the @Profile annotation, a suitable data source will be invoked by the test class.

@Profile Annotation in Spring 4

@Profile Annotation

The syntax for this annotation is @Profile(“dev”). If a bean or method marked with annotation will be associated with that particular profile name. This example uses the method type annotation (Spring 4 improvements). Where as you also do it in the class level.

@ActiveProfiles Annotation
How do we tell the container that which profile is active now to pick up the right configurations. We have to use @ActiveProfiles to tell the currently active profile. This can be done through XML, JavaConfig, Annotations and Programatically.

Annotation Configuration

@ActiveProfiles(profiles = "dev")
public class DevConfigTest {
//code here
}


Web.xml Configuration


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


Programatic Configuration

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//Enable a "live" profile
context.getEnvironment().setActiveProfiles("live");


@Profile Annotation Example

Here is the example application using @Profile annotation.

Student.java
AnnotationConfigApplicationContext context = 
                             new AnnotationConfigApplicationContext();
//Enable a "live" profile
context.getEnvironment().setActiveProfiles("live");

package aid.net.spring.core;

public class Student {
 private String id;
 private String name;
 private String grade;

 public Student(String id, String name, String grade){
  this.id = id;
  this.name = name;
  this.grade = grade;
 }

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getGrade() {
  return grade;
 }

 public void setGrade(String grade) {
  this.grade = grade;
 }
}


DevEnvConfig.java

package aid.net.spring.core;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("dev")
public class DevEnvConfig {
 @Bean
 public Student user(){
  return new Student("001", "Dev Student 1","Grade 1");
 }
}


ProdEnvConfig.java

package aid.net.spring.core;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("prod")
public class ProdEnvConfig {
 @Bean
 public Student user(){
  return new Student("002", "Prod Student 1","Grade 2");
 }
}


ProductionDataSourceConfig.java

package aid.net.spring.core;

import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("prod")
public class ProductionDataSourceConfig {
   @Bean
   public DataSource dataSource(){
  //Do connection related task
             return null;
   }
}


SpringProfileTest.java


package aid.net.spring.core;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringProfileTest {
 public static void main(String[] args) {
  AnnotationConfigApplicationContext ctx = 
   new AnnotationConfigApplicationContext();
  ctx.getEnvironment().setActiveProfiles("prod");
  ctx.scan("aid.net.spring.core");
  ctx.refresh();
  Student student = ctx.getBean(Student.class);
  System.out.println("\nStudent Id:" + student.
   getId() + ", \nStudent Name:" + student.getName()
    + ", \nStudent Grade : " + student.getGrade());
 }
}

Spring Boot @ConfigurationProperties and Properties File

 In this tutorial, you will learn to use @ConfigurationProperties to map properties files to POJO classes in Spring Boot application. Let’s ...