Validations with @ConfigurationProperties in Spring Boot

Examples of Validating YAML or Properties file configurations using @ConfigurationProperties in Spring Boot.

Overview

Spring Boot @ConfigurationProperties annotation is useful for mapping YAML or properties file configurations into a properties class, which is a plain java bean.

This tutorial focuses on Validating Application Properties in Spring Boot. In other words validating Configuration Properties that are mapped into a Java Bean. Good news is that, Spring Boot @ConfigurationProperties supports Java Bean validation specification – JSR-303 (doc).

If you are looking to learn more about the @ConfigurationProperties annotation, we recommend reading – Using @ConfigurationProperties in Spring Boot.

Validating Application Properties

The application YAML and Properties files contain the application level configurations and variables. Thus it is important to validate the Configuration Properties Bean and throw error is something is not correct. Adding field validations safeguards our applications from unwanted configurations.

Let’s add spring-boot-starter-validation dependency to our application.

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
Code language: HTML, XML (xml)

Doing so, Spring Boot enables Hibernate Bean validations that are based on javax.validation api.

Define @ConfigurationProperties Validations

Next snippet shows an application.yaml file from a Spring Boot application. This YAML contains configuration about some external server connection.

Sample application.yaml file

connection: host: 192.0.2.1 port: 8181 timeout: 30000 notify: support@example.com error-file: logs/error.log
Code language: YAML (yaml)

or, you may have an equivalent properties file.

Let’s create a @ConfigurationProperties class to bind the configuration into.

@Validated @Configuration @ConfigurationProperties(prefix = "connection") public class ValidatedProperties { }
Code language: Java (java)

Note that we have added @Validated annotation on top of the class.

To validate that the host property is not null or not blank, we will add @NotBlank annotation on the respective field.

@NotBlank private String host;
Code language: Java (java)

Similarly, we want the port number to be a valid port. Thus, we will use @Min and @Max annotations to provide a range of valid port numbers.

@Min(1025) @Max(65536) private int port;
Code language: Java (java)

The timeout value must be a valid positive number. Thus, we have used @PositiveOrZero annotation to ensure the timeout is not a negative number.

@PositiveOrZero private long timeout;
Code language: Java (java)

The YAML configuration provides an email address to which the error notifications to be sent. To ensure that that the given email address is valid we will add @Email annotation.

@Email private String notify;
Code language: Java (java)

Lastly, we want to ensure that the log file name must end with .log extension. To do so, we can write our own regular expression and use @Pattern annotation with regexp property.

@Pattern(regexp = "([^\\s]+(\\.(?i)(log))$)") private String errorFile;
Code language: Java (java)

Run and Verify

First, we will run our application with invalid configurations. The next application YAML file shows a group of connections properties. However based on the validation we added, all fields are invalid.

Invalid Application YAML file

connection: port: 123 timeout: -13000 notify: supportexample.com error-file: logs/error.txt
Code language: YAML (yaml)

As mentioned above, you can also have an equivalent properties file instead.

Having this configuration, our application will fail to start.

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

Description:

Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'connection' to com.amitph.spring.properties.validated.ValidatedProperties$$EnhancerBySpringCGLIB$$67a9fba0 failed:

    Property: connection.port
    Value: 123
    Origin: class path resource [application.yml] - 62:9
    Reason: must be greater than or equal to 1025

    Property: connection.notify
    Value: supportexample.com
    Origin: class path resource [application.yml] - 64:11
    Reason: must be a well-formed email address

    Property: connection.timeout
    Value: -13000
    Origin: class path resource [application.yml] - 63:12
    Reason: must be greater than or equal to 0

    Property: connection.errorFile
    Value: logs/error.txt
    Origin: class path resource [application.yml] - 65:13
    Reason: must match "([^\s]+(\.(?i)(log))$)"

    Property: connection.host
    Value: null
    Reason: must not be blank


Action:

Update your application's configuration

As seen here, Spring provides very detailed summary of the validation errors. This is useful for rectifying the invalid configurations.

Lastly, let’s start our application with a valid set of configurations.

connection: host: 192.0.2.1 port: 8181 timeout: 30000 notify: supportexample.com error-file: logs/error.log
Code language: YAML (yaml)

We will print the application properties instance upon startup.

* Validated Properties
host: 192.0.2.1
port: 8181
timeout: 30000
notify: support@example.com
errorFile: logs/error.log

The output shows the application starts up and all the application properties are correctly loaded.

Summary

In this quick tutorial covered examples of Validating Spring Boot Application Properties or YAML configurations. Spring Boot @ConfigurationProperties support java validation specification (JSR 303) and we can easily plug in the validation using annotations.

We created a Spring Boot @ConfigurationProperties class and added some basic validations like @NotBlank, @Min, @Max, @PositiveOrZero, and @Email. Moreover, we have also seen an example of adding custom validations using Java Regular Expression with @Pattern annotation. Lastly, we learned that Spring Boot provides detailed error messages, when one or more fields fail the validation.

For the full source code of the examples used in this tutorial, you can refer to our Github Repository.