What is Spring Boot Profiles

Generally software applications, we need to be able to run it under different environments or under different setups. For example, say our application sends emails. For sending emails we need to configure SMTP servers with correct server URL, user, password etc. While developing we will generally have different SMTP servers credentials then the Production servers. Let's assume we have two different kinds of environments, dev- Development and prod-Production. So we would like to run the same code in dev and prod environments but with different configurations for email. Similarly we might have similar requirements for database, logs, security, etc, where we want to have different services/configurations plugged while in developing vs in productions. Spring Profiles helps to segregate our application configurations and make them available only in certain environments. 
In this article, we will dive into a situation where we would like to use different configurations in different environments. To achieve this high level we need two things,
1) Way to provide different configurations under different environments
2) Way to use environment-specific values in our app.
In the following example, we have two profiles and two property files. We have a java class MailSenderProperties which encapsulates the email configuration. Spring Boot will populate MailSenderProperties based on the profile that is active.

Profile and Properties files

Property file naming scheme
The property file is generally named by application HYPHEN PROFILENAME HYPHEN.properties.
application-{_profile_}.properties
We have two profiles (dev, prod) and two profile-specific property files. application-dev.properties application-prod.properties Now based on the profile we set active the property values would be read from the corresponding properties file.

Properties files

application-dev.properties
This is the property file for dev profile.
mail.smtp.host=mail.dev.com
mail.smtp.port=7777  
mail.smtp.user=test_dev 
application-prod.properties
This is the property file for prod profile.
mail.smtp.host=mail.prod.com
mail.smtp.port=8888  
mail.smtp.user=prod_user
application.properties
This is the common property file, which contains general configurations like logging level and also the active profile.
#Other configurations
spring.profiles.active=dev
logging.level.root=info

Mapping the Profile specific value to java class

MailSenderProperties
Java class to encapsulate the MailSender values, which are read from the application-PROFILE.properties file. We use the @PropertySource annotation and specify the respective property file that should be used by classpath:application-${spring.profiles.active}.properties
@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;
  }
}

Setting Active Profile

We can set the active profile a number of ways. Some of the ways we need to change code to set the active profile. Here we will cover some fo the ways to set the active profile without changing code. 1) Set an active profile in the application.properties file ( dev is the active profile) spring.profiles.active=dev 2) set the active profile via an environment variable ( prod is the active profile) export spring_profiles_active=prod
Summary
  • Though using Spring Profile we can use a different set of properties under different circumstances
  • Spring profile can be set both programmatically and though environment variables
  • We can have more than one active profile settings at any time.
  • If we don't set any profile then Spring boot uses a profile called default profile.

Next Reading


Externalizing configuration properties

Spring Boot is developer-friendly and supports a number of features to increase productivity. One of them is externalizing configuration properties. Externalizing configuration properties means that all the configuration values are not hardcoded in the application and hence we can change the values as needed while deploying the application. Spring Boot supports a number of different ways to externalize properties and read them in the application.
We can have properties defined in various locations( different property files ) and various sources (property files, command line, System Properties, etc.), spring boot uses a specific order to read the values from those sources, which also enables us to override values. For example, we may provide some default values to the application, then while running it we might want to override some values.
The following are some of the places from where the application can read property values. The list is in descending priority. For example, property values passed though command-line argument will override Java system properties or default properties.
Property value priority order (Descending priority)
  • Command-line arguments.
  • Java System properties.
  • OS level environment variables.
  • @PropertySource annotations classes.
  • Application properties outside of your packaged jar.
  • Application properties packaged inside your jar.
  • Default properties.

Accessing properties values

Spring Boot provides multiple ways to access property values. The following are some of the ways. We will be using the bellow property file (office-address.properties) to demonstrate some of the ways to access the values defined in it.
office-address.properties
Property file which contains properties names and values. We will read this property to java classes by using @Value and @ConfigurationProperties
#Sample Property file
contact.from=admin
contact.fromEmail=admin@bootng.com
contact.fromPhone=Hello from bootng
contact.fromTwitter=@BootNGTweet

address.street=1901 Palo Alto Avenue
address.city=Palo Alto
address.state=California
address.zip=950441

Reading with @Value annotation

@Value
With @Value annotation, we can map a particular property to a java class field. Here we mapped different fields of the class AddressProperties to the properties in the office-address.properties by individual @Value annotations.
@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;
}

Reading with @ConfigurationProperties annotation

@ConfigurationProperties
@Value is good when the properties are small in number. But say we want many properties to individual fields in the Java Class then we can use ConfigurationProperties. Spring will map the field name with the property name and will populate the value automatically. In the bellow example the filename twitterHandle does not match with the property fromTwitter. So with @ConfigurationProperties Spring boot will not be able to match the field with corresponding property and hence it would be null. To fix the issue we can use @Value("${contact.fromTwitter}") for the twitter field to populate it with @Value annotation.
@Component
@ConfigurationProperties(prefix = "contact")
@PropertySource("classpath:office-address.properties")
public class ContactProperties {

  private String from;

  private String fromEmail;

  @Value("${contact.fromTwitter}")
  private String twitterHandle;

  public String getFrom() {
    return from;
  }

}

Validating properties

@Validated Annotation
@Validated Annotation can be used to validate the field values. Spring Boot supports many validation rules, like NotNull, Email, NotEmpty, etc. Similar to the above class but now we have decorated the class with @Validated annotation and marked some of the fields with @NotNull and @Email validations. Doing so, if the values for these fields do not comfort to the validation rules defined, Spring Boot will throw expectation.
@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;
  }
}
Summary
  • We can use @Value annotation to map individual properties from the property file.
  • We can use @ConfigurationProperties to map all the fields of a class with respective properties from the property file.
  • With @ConfigurationProperties the field name in the class and property name should match.
  • With @ConfigurationProperties the prefix if provided is used to filter properties with matching name.
  • We can use both @Value and @ConfigurationProperties in the same class.
  • We can also validate the field values along with populating using @Validated annotation.

Introduction

This article show how to write a very simple Hello World Application in Spring. This application can be used as starting point for other applications.
We will go though the main components of the application, also code for the whole project is provided to download and play with it.

Technologies used

  • Java 11
  • Spring Boot 2.2.6.RELEASE
  • Maven 3.5.0
  • Eclipse IDE
This is a very simple Spring boot application with just one controller. The intention of the Application is to build a web app that when accessed will return a String message. This project is intended to help understand how to build a very simple Spring Application. So we are not touching other concepts like configuration, Profiles, etc.

Project Structure



Project code reference

The following paragraphs show important files for this sample project. Like the pom.xml file, HelloApplication.java (Spring Boot Application class) and the Controller class which is responsible for serving the request (HelloController.java)
pom.xml
<?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-hello</artifactId>
 <version>1.0.0</version>
 <packaging>war</packaging>
 <name>Spring Boot Hello</name>
 <description>Spring Boot Hello Simple Application</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>
 </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
Spring Boot entry class that would be loaded and executed once the application boots up. It does not do much except that it has the annotation @SpringBootApplication to tell the spring boot framework that this is the entry point class. Also, it has @ComponentScan, so that Spring boot framework can scan and load any components from package com.bootng.
package com.bootng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ComponentScan({"com.bootng"})
@SpringBootApplication
public class HelloApplication {
  private static final Logger log = LoggerFactory.getLogger(HelloApplication.class);
  public static void main(String args[]) {
    log.info("about to call HelloApplication.run()");
    SpringApplication.run(HelloApplication.class, args);
    log.info("completed executing HelloApplication.run()");
  }
}
HelloController
Our only Controller class that is mapped to the path /hello and return a String as a response.
package com.bootng;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
  @RequestMapping("/hello")
  public  @ResponseBody String hello() {
    return "Hello Spring Boot!";
  }
}

Run hello spring boot app

Build and Run Application
run the following command in the console to build the application and then run the application.
mvn clean install
mvn spring-boot:run
Console (Portion of the terminal logs)
INFO main c.b.HelloApplication:651 - No active profile set, falling back to default profiles: default 
INFO main o.s.b.w.e.t.TomcatWebServer:92 - Tomcat initialized with port(s): 8080 (HTTP)
INFO main o.a.c.h.Http11NioProtocol:173 - Initializing ProtocolHandler ["http-nio-8080"]
INFO main o.a.c.c.StandardService:173 - Starting service [Tomcat]
INFO main o.a.c.c.StandardEngine:173 - Starting Servlet engine: [Apache Tomcat/9.0.33]
INFO main o.s.b.w.e.t.TomcatWebServer:204 - Tomcat started on port(s): 8080 (http) with context path ''
Started HelloApplication in 1.384 seconds (JVM running for 1.716)
INFO main c.b.HelloApplication:18 - completed executing HelloApplication.run()
Access the application by
typing in the browser.
 http://localhost:8080/hello
We should be able to see the page returning the message from the controller.
Download source code
  • git clone https://github.com/bootng/spring-boot-references
  • cd bootng-springboot-hello
  • mvn install
  • mvn spring-boot:run

    Summary

    • This article shows how to build a sample web application from scratch.
    • This is a Maven-based project, similarly, we can have a Gradle based project also.
    • For the mvn install step, we need to be connected to the internet.
    • This is a simple web app that has only one request path mapped.
    • If we try with different paths then this App will show an error page.

    Introducing Spring Boot Initializer

    Spring Boot Initializer is a web app that helps in bootstrapping spring boot projects. Though the Spring Boot Initializer we can quickly provide dependencies, choose a Build tool like Maven, Gradle, etc, and generate the codes along with configurations. The following image shows spring boot Initializer web app.

    Initializer Web App
    Spring Boot Initializer Web App

    How to generate code

    To generate the code please follow the following steps
    • Go to https://start.spring.io/
    • Select project build tools (Maven, Gradle).
    • Select the language (Java, Kotlin, Groovy).
    • Select Spring Boot Version
    • Provide the meta-information like the artifact name, descriptions, etc.
    • Select Java version.
    • Select Packaging.
    • And also select the dependencies based on the need for the project.
    We can always add more dependencies, change the java version, etc. from the generated project code.
    This will allow the web app to create a sample project with sample codes and dependencies which will be downloaded to your computer. 

    Sample generated project.

    The following image shows a code structure for a sample web project generated.


    Demo of code generation.

    Following video shows a demo of code generation using the web app.

    References

    Summary

    • Spring Boot initializr web app can be used to bootstrap project.
    • The downloaded source code contains all dependencies and sample classes.
    • We can also start by cloning or forking an existing git repository.

    Spring Boot

    Spring Boot is an open-source framework to create Applications with minimum configurations. Spring boot provides a range of non-functional features that are common to applications like embedded servers, health checks, externalized configuration, CLI, etc. With Spring Boot, we can focus more on actual application logic and less on infrastructure. Some of the important features and concepts related to Spring Boot are listed below, which helps in getting started with Spring Boot.

    Entry Point of Application

    The entry point for any Spring Application is a class decorated with @SpringBootApplication annotation. This class contains the main method which will be invoked when the application boots.

    Component Scan

    Spring Boot uses a lot of annotation to increase developer productivity. For Applications to discover and initialize other components, Spring Boot uses @ComponentScan annotation. We can specify other Classes or packages that need to be scanned and initialized.

    Configuration

    Spring boot supports deferent ways of reading application configurations. We can provide configurations in YAML files or properties files or Java POJO Classes.

    Profiles

    Spring Boot supports Spring Profiles, which is a kind of different set of configuration values for different environments. For instance, we can have different database credentials for Production vs Test environments. Here we can put the database credentials values different under different Profiles.

    Build Tools

    Spring Boot supports different Build environments and technologies. For instance, we can use a maven to configure the build infrastructure, or we can also use Gradle, etc.

    Spring Boot Starters

    Spring boot can be used to develop a range of applications along with using different third party libraries. Spring boot starters provide pre-bundled dependencies for a particular type of application. In the Spring Boot Framework, all the starters follow a similar naming pattern: spring-boot-starter-*, where * denotes a particular type of application. For example if we want to develop an application based on Elastic Search we can use the starter spring-boot-starter-data-elasticsearch to bootstrap the application.