Spring Boot Profile Example Details


Example with Spring Profiles

In continuation of the Spring Boot profiles, in this article we will walk through different use cases. We will see how to read property files and display them through a controller. We have following use cases 1)Defining and reading profile-specific beans 2) populating beans from a properties file.

Purpose

In this article, we will build a Spring Boot Application with a two-controller and 2 profile-specific configuration files.

Code structure


Spring Boot Application Structure


Technology Used
Java 11
Spring Boot 2.2.6.RELEASE
Maven 3.5.0
Eclipse IDE

Application details

This application we have one controller EmailController which shows some data to the response. These data are collected from different Java classes. Each java class is populated by Spring in a different way. PaymentProperties: This defines a bean-based on profile. When we read the bean PaymentProp from EmailController it shows the data based on the active profile. MailSenderProperties: It is populated by the active profile property file. ContactProperties and AddressProperties: These objects are populated from the respective properties file and have nothing to do with an active profile.

Code details

pom.file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <artifactId>bootng-springboot-profiles</artifactId>
 <version>1.0.0-SNAPSHOT</version>
 <packaging>war</packaging>
 <name>com.bootng Springboot Profile</name>
 <description>com.bootng Springboot Profile</description>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.6.RELEASE</version>
  <relativePath />
 </parent>
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.junit.jupiter</groupId>
   <artifactId>junit-jupiter-api</artifactId>

  </dependency>
 </dependencies>
 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
     <addResources>true</addResources>
    </configuration>
    <executions>
     <execution>
      <goals>
       <goal>repackage</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
 </build>
</project>
Application Class
@ComponentScan({"com.bootng", "com.bootng.service"})
@SpringBootApplication
public class RestApplication {
  private static final Logger log = LoggerFactory.getLogger(RestApplication.class);
  public static void main(String args[]) {
    log.info("about to call RestApplication.run()");
    application.run(args);
    log.info("completed executing RestApplication.run()");
  }
}
EmailController
package com.bootng;

@Controller
public class EmailController {
  @Autowired
  public MailSenderProperties mailSender;
  @Autowired
  private ContactProperties contact;
  @Autowired
  private AddressProperties address;
  @Autowired
  private ApplicationContext applicationContext;
  @Value("${appserver.version}")
  private String paymentServerVer;
  @RequestMapping(value = {"/details"}, method = RequestMethod.GET,
      produces = MediaType.APPLICATION_JSON_VALUE)
  public @ResponseBody ResponseEntity <String> paymentInfo() {
    
    //Get the Bean with name PaymentProp
    HashMap<String, String> paymentProp = (HashMap<String, String>) applicationContext.getBean("PaymentProp");
    
    //Get the payment Server version from application.properties file
    String paymentInfo ="\nPayment Server Version:= " +  paymentProp.toString();
    
    String smtpInfo = "\n Mail Server SMTP Host: " + mailSender.getSmtpHost() + " SMTP Port:"
        + mailSender.getSmtpPort();
    
    String info = "\nContactInfo From=" + contact.getFrom() + " Email=" + contact.getFromEmail();
    String addressInfo = "\n AddressInfo Street=" + address.getStreet() + 
                         " City=" + address.getCity() +
                         " State=" + address.getState() +
                         " Zip=" + address.getZip();
    String result = paymentInfo + smtpInfo + info + addressInfo;
    return new ResponseEntity<String>(result, HttpStatus.OK);
  }
  
  @RequestMapping(value = {"/smtp"}, method = RequestMethod.GET,
      produces = MediaType.APPLICATION_JSON_VALUE)
  public @ResponseBody ResponseEntity<String> sendEmail() {

    String result = "<br>Mail Server SMTP Host: " + mailSender.getSmtpHost() + " SMTP Port:"
        + mailSender.getSmtpPort();

    return new ResponseEntity<String>("email sent" + result, HttpStatus.OK);
  }
  
  @RequestMapping(value = {"/address"}, method = RequestMethod.GET,
      produces = MediaType.APPLICATION_JSON_VALUE)
  public @ResponseBody ResponseEntity <String> getAddress() {
  
    String info = "From=" + contact.getFrom() + " Email=" + contact.getFromEmail();
    String addressInfo = " Street=" + address.getStreet() + 
                         " City=" + address.getCity() +
                         " State=" + address.getState() +
                         " Zip=" + address.getZip();
   
    return new ResponseEntity<String>(info + addressInfo, HttpStatus.OK);
  }
}
PaymentProperties
@Configuration
public class PaymentProperties {
  @Profile("dev")
  @Bean(name="PaymentProp")
  public HashMap<String, String> getPaymentServerDev() {
      HashMap<String, String> paymentMethod = new HashMap<>();
      paymentMethod.put("Currency", "USD");
      paymentMethod.put("ChargePercentage", "1");
      paymentMethod.put("Gateway", "BOA");
      return paymentMethod;
    }
  @Profile("prod")
  @Bean(name="PaymentProp")
  public HashMap<String, String> getPaymentServerProd() {
      HashMap<String, String> paymentMethod = new HashMap<>();
      paymentMethod.put("Currency", "Pound");
      paymentMethod.put("ChargePercentage", "4");
      paymentMethod.put("Gateway", "BankOfEngland");
      return paymentMethod;
    }
}
MailSenderProperties
@Component
@PropertySource("classpath:application-${spring.profiles.active}.properties")
public class MailSenderProperties {
  @Value("${mail.smtp.host}")
  private String smtpHost;

  @Value("${mail.smtp.port}")
  private Integer smtpPort;
  public String getSmtpHost() {
    return smtpHost;
  }
  public void setSmtpHost(String smtpHost) {
    this.smtpHost = smtpHost;
  }
  public Integer getSmtpPort() {
    return smtpPort;
  }
  public void setSmtpPort(Integer smtpPort) {
    this.smtpPort = smtpPort;
  }
}
ContactProperties
@Component
@ConfigurationProperties(prefix = "contact")
@PropertySource("classpath:office-address.properties")
@Validated
public class ContactProperties {
  @NotNull
  private String from;
  @Email
  private String fromEmail;
  @Value("${contact.fromTwitter}")
  private String twitterHandle;

  public String getFrom() {
    return from;
  }
  public void setFrom(String from) {
    this.from = from;
  }
  public String getFromEmail() {
    return fromEmail;
  }
  public void setFromEmail(String fromEmail) {
    this.fromEmail = fromEmail;
  }
  public String getTwitterHandle() {
    return twitterHandle;
  }
  public void setTwitterHandle(String twitterHandle) {
    this.twitterHandle = twitterHandle;
  }
}
AddressProperties
@Component
@PropertySource("classpath:office-address.properties")
@Validated
public class AddressProperties {
  @Value("${address.street}")
  private String street;
  @Value("${address.city}")
  private String city;
  @Value("${address.state}")
  private String state;
  @NotNull
  @Value("${address.zip}")
  private String zip;
  public String getStreet() {
    return street;
  }
  public void setStreet(String street) {
    this.street = street;
  }
  public String getCity() {
    return city;
  }
  public void setCity(String city) {
    this.city = city;
  }
  public String getState() {
    return state;
  }
  public void setState(String state) {
    this.state = state;
  }
  public String getZip() {
    return zip;
  }
  public void setZip(String zip) {
    this.zip = zip;
  }
}
application-dev.properties
logging.level.root=info
mail.smtp.host=mail.dev.com
mail.smtp.port=7777  
mail.smtp.user=test_dev 
application-prod.properties
logging.level.root=info
mail.smtp.host=mail.prod.com
mail.smtp.port=8888  
mail.smtp.user=prod_user
Run with profile prod
Run the application with prod profile set to active and then when the application is started, go to http://localhost:8080/details
mvn spring-boot:run -Dspring-boot.run.profiles=prod
Browser Output
Payment Server Version:= {Gateway=BankOfEngland, Currency=Pound, ChargePercentage=4} Mail Server SMTP Host: mail.prod.com SMTP Port:8888 ContactInfo From=admin Email=admin@bootng.com AddressInfo Street=1901 Palo Alto Avenue City=Palo Alto State=California Zip=950441
Run with profile dev
Stop the running application. And then restart with profile = dev
mvn spring-boot:run -Dspring-boot.run.profiles=dev
Browser Output
Payment Server Version:= {Gateway=BOA, Currency=USD, ChargePercentage=1} Mail Server SMTP Host: mail.dev.com SMTP Port:7777 ContactInfo From=admin Email=admin@bootng.com AddressInfo Street=1901 Palo Alto Avenue City=Palo Alto State=California Zip=950441
Download Source code
git clone git@github.com:bootng/spring-boot-references.git cd sping-boot-profiles mvn clean install mvn spring-boot:run -Dspring-boot.run.profiles=dev

Conclusion

This article shows different ways we can use Profiles in Application. We can see different values in the Controller output based on the profile. We can have multiple profiles active, but this article deals with only setting one profile at a time. Can you guess what will happen with this application and multiple profiles set active?

No comments :

Post a Comment

Please leave your message queries or suggetions.