@ConfigurationProperties in Spring Boot

 

 

Introduction to @ConfigurationProperties in Spring Boot

In this article of Spring Boot tutorial, we will cover @ConfigurationProperties in Spring Boot. Spring Boot provides a very clean way to load properties for an 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 use it in the following way

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

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

 

2. Setup

We need no special setup to enable <i>@ConfigurationProprties</i> 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

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 we define all these properties 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 need not be an exact match between the properties. For a property db.username, all the following variations are valid in Spring Boot property binding

Property Name Description
db.userName  
db.user-name  Dashed notation will work for username
db.user_name  underscore notation
db.USER_NAME upper case format

 

4. Property Validation

We can use JSR-303 Validation API to validate property defined using@ConfigurationProperties. To use bean validation with Spring Boot, we need to add JSR-303 compliant validation API in our project. For this post, I will use 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 over 10.

To achieve this, we will add 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.config.ApplicationConfigurationProp$$EnhancerBySpringCGLIB$$de8c01c7@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 show 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 a way to validate injected properties using JSR-303 Bean Validation API. At the end we briefly touched 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.

10 thoughts on “@ConfigurationProperties in Spring Boot”

  1. Question:
    Can we update the configuration dynamically, like handle the DB connection by using a local variable?

    working connection:
    @ConfigurationProperties(prefix = “spring.user.datasource”)

    To BE (if possible, DbConnection will hold “spring.user.datasource” or some other db connection details)
    @ConfigurationProperties(prefix = DbConnection)

    OR any other method where we can handle connection explicitly.

    More Details:
    I have a functionality, which needs to run in different database, database will be changed thru UI dropdown. I want to avoid creating multiple config files to run same functions.

    • Not sure If I understood your question, but creating database connection run time is not very intuitive and efficient.If you want to do that, you can create a database connection programmatically and even can store all the DB connection details in a separate table.
      If we are only talking about that based on the selection, we only wan to use different connection bean for the work, we can easily do that by crating 2 different connection bean and use a simple strategy to choose the correct bean at run time based on the user selection.

Comments are closed.