@ConfigurationProperties in Spring Boot

Introduction to @ConfigurationProperties in Spring Boot

In this article, we will be covering @ConfigurationProperties in Spring Boot. Spring Boot provides a very clean way to load properties for a given application.It provides an easy and manageable way to externalized configurations along with the ability to bind and validate these configurations.

 

1. Introduction

Consider following entries in a property file (say custom.properties)

user.firstName = Umesh
user.lastName = Awasthi
user.greeting = Hello Umesh
user.blogName = umeshawasthi.com

If I have to use these property files in the Spring application (without Spring Boot), I will be using it in following way

public class SimpleSpringPropertyTest {
    @Value("${user.firstName}") private String firstName;
    @Value("${user.lastName}") private String lastName;
 } 

@Value("${proprties}") annotation is quite handy and easy to use, but it will really be a very tedious process if we have a number of properties. Spring Boot has introduced a new approach to handling these properties in a more clean way with an option to validate these configuration value.

 

2. Setup

We do not need any special setup to enable @ConfigurationProprties feature in Spring Boot, We need to define spring-boot-starter-parent as our parent in our project’s pom.xml

<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>1.5.3.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>

Above entry in pom.xml will ensure that all required dependencies are in your class path.

 

3. Introduction to @ConfigurationProprties

In order to understand this feature, we can take an example of a custom property file which contains configuration properties for Database, Email Server and something else, on a high level that property might look like


#Database Configuration

db.driver =org.hsqldb.jdbcDriver
db.username	=test
db.password	=test
db.tablePrefix =_prefix

#SMTP Configuration

mail.from [email protected]	 
mail.host [email protected]
mail.port =25
mail.security.userName 	=test
mail.security.password 	=test

#Server Configurations

server.tomcat.httpPort =80
server.tomcat.sslPort =443
server.tomcat.ajpPort =444
server.tomcat.jmxPort =445

#Global Properties
username=umesh
welcomeMessage = Welcome Umesh!!!

3.1 Binding Properties

We will start by creating a separate POJO class to store and handle our application specific configuration properties by annotating it with @ConfigurationProperties 

@Configuration
@ConfigurationProperties
public class ApplicationConfigurationProp {

}

@Configuration annotation will allow Spring to detect and register this Bean which means we can inject this configuration bean in our application. Above code will work fine if we want to access only global properties (i.e. username and welcomeMessage).

@Configuration annotation is most suitable when we want to access hierarchical properties and we want to access/filter properties based on the prefix. Let’s say we want to bind all the properties starting with prefix “mail” to our  ApplicationConfigurationProp  Class, we can use prefix property on the @ConfigurationProperties annotation.

 

@Configuration
@ConfigurationProperties(prefix = "mail")
public class ApplicationConfigurationProp {


    private String from;
    private String host;
    private int port;

    //getter and setter

    public static class Security{
        private String userName;
        private String password;

        //getter and setter
    }

}

Once we run above application, all properties defined in the property files with prefix “mail” will automatically be bind / assigned to this object.

 

3.2 Binding Custom Properties File

While working on the above example we assume that all these properties are defined in the Spring Boot’s application.properties file, let’s say we want to define these properties in our custom property file (custom.properties) and not in the application.properties file. We can use @PropertySource annotation to define custom property file.

@Configuration
@PropertySource("classpath:custom.properties")
@ConfigurationProperties(prefix = "mail")
public class ApplicationConfigurationProp {
}

 

3.3 Relaxed binding

One of the interesting features of the Spring Boot property binding is “relaxed binding rules”. Under relaxed binding, Spring Boot doesn’t need to be an exact match between the properties.

For a given property db.username, all of the following variation are valid in Spring Boot property binding

Property NameDescription
db.userName 
db.user-name Dashed notation will work for username
db.user_name underscore notation
db.USER_NAMEupper case format

 

4. Property Validation

We can use JSR-303 Validation API to validate property defined using@ConfigurationProperties. In order to use bean validation with Spring Boot, we need to add JSR-303 compliant validation API in our project. For this post, I will be using Hibernate Validator by adding it in our pom.xml file

<dependency>
    <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>5.4.1.Final</version>
   <relativePath/>
</dependency>

We need to add standard @Validated annotation in order for bean validation to validate given bean. To understand how Bean Validation will work with @ConfigurationProperties let’s take an example where we want to ensure that userName should be validated against following rules

  1. Minimum length of username should be 5
  2. User Name length can not be more than 10.

In order to achieve this, we will be adding JSR-303 javax.validation constraint annotations directly on your configuration class.

@Configuration
@PropertySource("classpath:custom.properties")
@ConfigurationProperties(prefix = "mail")
@Validated
public class ApplicationConfigurationProp {

    @Valid
    private Security security= new Security();

    public static class Security{

        @Length(max = 10, min = 5)
        private String userName;

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }
    }

}

We have following property file defined in our custom.properties file 

mail.security.userName  =test

If we run our application, Spring Boot will try to bind userName property in our configuration class and it will throw error as validation will fail for the given property


***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target com.umeshawasthi.confi[email protected]69637b10 failed:

    Property: mail.security.userName
    Value: test
    Reason: length must be between 5 and 10


Action:

Update your application's configuration

I have used .properties file in this post, Please note that @ConfigurationProperties supports both .properties and .yml file

5. Complex or Nested Properties

I have taken a simple example (with nested class) to demonstrate how Spring Boot can map these properties in our configuration class, We can use similar techniques to bind even complex hierarchy using Spring Boot’s @ConfigurationProperties

app.servers[0]=dev.test.com
app.servers[1]=foo.test.com

To bind above properties using Spring Boot’s @ConfigurationProperties, We only need to define properties in the target bean either as a java.util.List, or Set. Converting these properties in to List or Map will be handled by Spring DataBinder. (You can even register your custom Data Binder to map custom properties).

@ConfigurationProperties(prefix="app")
public class AppConfig {

    private List servers = new ArrayList();

    public List getServers() {
        return this.servers;
    }
}

Summary

In this post, we explored @ConfigurationProperties in Spring Boot. We explored how this is being used by Spring Boot to bind properties in our object. We checked how to specify customer property path for binding properties and way to validate injected properties using JSR-303 Bean Validation API. We touched briefly relax binding feature. 

Spring Boot Provides a very clean and flexible approach to bind property files in configuration object.

 

Complete Example

All the code of this article is available Over on Github. This is a Maven-based project.

You May Also Like

Leave a Reply

Be the First to Comment!

Notify of
avatar
wpDiscuz