Open In App

Spring Boot – @ConfigurationProperties

Last Updated : 03 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In Spring Boot, @ConfigurationProperties Annotation allows the developer to map the entire content of the properties file to a POJO (Plain Old Java Object). A property file can be either application.properties or application.yml. This annotation is useful when we have a large set of explicit configurations defined in the properties file. It provides an organized and Java-specific approach to defining the properties. We can cluster similar sets or properties to multiple POJOs.

In this article, we’ll discuss the @ConfigurationProperties Annotation of Spring Boot Framework for that supports binding an external property file to a Java Object.

@ConfigurationProperties in Spring Boot

A real-world example to better understand the isolation of a properties file in a separate POJO would be:

You can organize all your books on your table depending on their genres but the problem with this approach is that you’ll have to go through the covers of one or more books to identify which genre this particular stack belongs to. Now, imagine putting them on a shelf, and labeling the partitions of the shelf with books of each type wouldn’t that be easy? Isolating property files in separate POJOs allows you to achieve similar functionality.

It is also recommended by Spring Framework’s official document to isolate property files in separate POJOs.

Properties file mapped to POJOs

Step-By-Step Implementation

Step 1: Go to Spring Initalizr and download and extract a starter file.

We need following set of things:

  • Spring Web Dependency
  • Java 8 or higher
  • IDE for Java (We’ll be using Intellij in this article)
  • Lombok (Optional)
  • JDBC API
  • MySQL Driver
  • Validation

Project Metadata

pom.xml File:

XML




<?xml version="1.0" encoding="UTF-8"?>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.GeeksForGeeks</groupId>
    <artifactId>ConfigurationProperties</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>ConfigurationProperties</name>
    <description>Demo project for @ConfigurationProperties</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
  
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
  
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
  
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
  
</project>


Step 2: Organize directory structure

  • Create a new package to store Configuration Property Java Objects (POJOs) – ConfigProperties
  • Create these classes under the ConfigProperties Package – DatabaseConfigProperties and ServerProperties
  • Create another package to store the REST Controllers for validation and verification of mapping of properties to the Java Objects.

Final directory structure should look like this:

Directory Structure

Step 3: Create a properties file

Store the following properties under – “src/main/resources/application.properties”

#1 Server Configuration Properties
server.port=8080
server.contextPath=/myPropertiesApp
server.connectionTimeout=5000

#2 Database Configuration Properties
spring.datasource.url=jdbc:mysql://localhost:3306/geeksforgeeks
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root


Step 4: Define Configuration Properties classes.

1. Server Properties Class

It is a simple plain old Java object defined for storing server type properties. Annotations used here have a significant impact on our Java Object’s working:

  • @Component: It’s to simply make our Java Object eligible for component scanning and registering it with Spring Container
  • @Data: It signify that this is a POJO, that only contains DATA. Getters and Setters are automatically generated using this annotation.
  • @Validated: It ensure that the properties mapped doesn’t have any error
  • @ConfigurationProperties: Defines the prefix for accessing a specific type of property. In the below example, we’ve implemented a Server Property Java Object to store server related properties so, its prefix is – “server”
  • @Min and @Max defines the range of port numbers that can be used
  • @NotBlank: It is used for ensuring that a particular property cannot be left blank
  • @Value: It is for providing a default value if none is provided in a property file

Java




import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.validation.annotation.Validated;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
  
// POJO for Server Property type
@Component
@Data
@Validated
@ConfigurationProperties(prefix = "server")
public class ServerProperties {
      
      // Range of port numbers
      @Min(1025)
    @Max(65535)
    private int port;
  
      // NotBlank indicates this property cannot be left blank
    @NotBlank(message = "Context path cannot be blank!")
    private String contextPath;
      
      // Specifying the default value if none is given inside properties file
    @Value("${server.connectionTimeout:5000}")
    private int connectionTimeout;
  
}


2. Database Configuration Properties Class

It is also a Plain Old Java Object defined for mapping database configuration properties, and we’ve also provided a prefix spring.datasource indicating all the properties starting with this will be mapped to this POJO.

Java




import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
  
// POJO for Database Configuration Property type
@Component
@Data
@Validated
@ConfigurationProperties(prefix = "spring.datasource")
public class DatabaseConfigProperties {
    @NotBlank(message = "URL field cannot be Blank!")
    private String url;
  
    @NotBlank(message = "You should specify the appropriate driver class!")
    private String driverClassName;
  
    @NotBlank(message = "Username field cannot be Blank!")
    private String username;
  
    @NotBlank(message = "Password field can not be Blank!")
    private String password;
}


Step 5: Create REST Controller to fetch & verify the mapping of properties from property file to POJOs

REST Controller:

Java




import com.GeeksForGeeks.ConfigurationProperties.ConfigProperties.DatabaseConfigProperties;
import com.GeeksForGeeks.ConfigurationProperties.ConfigProperties.ServerProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
  
// Controller to test Properties POJOs
@RestController
@RequestMapping("/properties")
public class TestController {
  
    // Field Injection
    @Autowired
    ServerProperties serverProperties;
  
    // Field Injection
    @Autowired
    DatabaseConfigProperties databaseConfigProperties;
  
    // Get Server Properties
    @GetMapping("/server")
    public ServerProperties getServerProperties() {
        return serverProperties;
    }
  
    // Get Database Properties
    @GetMapping("/database")
    public DatabaseConfigProperties getDatabaseProperties() {
        return databaseConfigProperties;
    }
}


Explanation of the above Program:

The above REST Controller defined, allows us to verify if the properties defined inside application.properties are mapped and stored properly in a POJO. We have defined following REST Endpoints:

  • http://localhost:8080/properties/server
  • http://localhost:8080/properties/database

We can define more properties and map them similarly by creating a separate POJO for each type. This approach promotes separation of concern and easily verify the mappings.

Output on PostMan:

1. http://localhost:8080/properties/server

Server Properties Output

2. http://localhost:8080/properties/database

Database Properties Output

Advantages

  • Centralized Configuration: This approach is providing a way to achieve a centralized configuration managing and organizing every type of property inside a POJO rather than searching it inside multiple files.
  • Performing Validation: You can directly perform validation on a POJO which can’t be done inside a property file its very important for debugging purposes. Example: @NotBlank, @Value etc.
  • Improved Readability and Testing: Isolating and mapping a specific type of property makes our code more readable and easily understandable. We can also directly mock different configuration values.

Disadvantages

  • Increased Boiler plate code: Using a POJO increase code because we have to include getters and setters, but we can overcome this overhead using Lombok Library
  • It won’t be suitable for an environment in which our configuration properties keep changing on regular intervals.

Conclusion

In conclusion, the @ConfigurationProperties is a way to map properties defined inside an application.properties file to a Java Object. This approach provides ease of access, validation, management, organization and improve the code readability of our application. Following are major key takeaways:

  • @ConfigurationProperties annotation is used on top of a Java Data Object to signify that it consists of mapped properties. An addition prefix is to be passed to instruct which type of properties will be mapped in this Java Object
  • This annotation provides addition features such as validation and verification of our properties file for security and debugging purposes.
  • Overall, this annotation helps us isolate and store a specific type of property into a Java Object.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads