The new Certification Class of Learn Spring Security is out:

>> CHECK OUT THE COURSE

1. Introduction

One of the handy features of Spring Boot is externalized configuration and easy access to properties defined in properties files.

An earlier article described various ways in which this can be done and in this article, we’re going to explore the @ConfigurationProperties annotation in greater detail.

2. Setup

The setup for this article is fairly standard. We start by adding spring-boot-starter-parent as the parent in our pom.xml:

<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

The latest version of Spring Boot can be found on the maven central here.

In order to be able to validate properties defined in the file, we would need a JSR-303’s implementation. hibernate-validator is one of them. Let’s add it to our pom.xml as well:

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

Depending on the type of application and the environment running, we might need to add one or more additional dependencies. The reference page has details about the same, and the latest version of hibernate-validator can be found here.

We shall take the example of a hypothetical class which has configuration properties related to a mail server to understand the full power of this annotation:

public class ConfigProperties {

    public static class Credentials {
        private String authMethod;
        private String username;
        private String password;

       // standard getters and setters
    }
    private String host;
    private int port;
    private String from;
    private Credentials credentials;
    private List<String> defaultRecipients;
    private Map<String, String> additionalHeaders;
 
    // standard getters and setters
}

3. Binding the Configuration Properties

According to the official documentation, it is recommended to isolate the configuration properties into a separate POJO annotated with @ConfigurationProperties, so let’s start by doing that:

@Configuration
@ConfigurationProperties
public class ConfigProperties {
    // previous code
}

We also have added the @Configuration annotation for Spring to be able to find this bean and make it a candidate for injection.

The annotation works best when we have hierarchical properties that all have the same prefix, so we mention the prefix too as a part of the annotation. We can also optionally define a custom source where we’re storing these properties, else the default location (

We can also optionally define a custom source where we’re storing these properties, else the default location (classpath:application.properties) is looked up. So we now add the above annotations to the existing properties class:

@Configuration
@PropertySource("classpath:configprops.properties")
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
    // previous code
}

That’s it! Now any properties defined in the property file that has the prefix mail and the same name as one of the properties are automatically assigned to this object.

Also, by default, a relaxed binding scheme is adopted for the binding, so all of the following variations are bound to the property authMethod of the Credentials class:

mail.credentials.auth_method
mail.credentials.auth-method
mail.credentials_AUTH_METHOD
mail.CREDENTIALS_AUTH_METHOD

Similarly, List and Map properties can also be bound. Here’s a sample properties file that binds correctly to our ConfigProperties object defined earlier:

#Simple properties
[email protected]
mail.port=9000
[email protected]

#List properties
mail.defaultRecipients[0][email protected]
mail.defaultRecipients[1][email protected]

#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true

#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1

4. Property Validation 

One of the handy things that this annotation provides the is the validation of properties using the JSR-303 format. This allows for all sorts of neat things like checking that a property is not null:

@NotBlank
private String host;

We can also check the minimum and maximum length of a String property:

@Length(max = 4, min = 1)
private String authMethod;

Or enforce the minimum and maximum value of an Integer property:

@Min(1025)
@Max(65536)
private int port;

And finally, we can also make sure that a property matches a certain pattern by defining a regex for the same. This has been done for email, as an example:

@Pattern(regexp = "^[a-z0-9._%+-][email protected][a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;

This helps us reduce a lot of if – else conditions in our code and makes it look much cleaner and concise.

If any of these validations fail then the main application would fail to start with an IllegalStateException till the incorrect property is corrected.

Also, it is important that we declare getters and setters for each of the properties as they’re used by the validator framework to access the concerned properties.

5. Conclusion

In this quick tutorial, we explored the @ConfigurationProperties annotation and also saw some of the handy features it provides like relaxed binding and Bean Validation.

As usual, the code is available over on Github.

Go deeper into Spring Security with the course:

>> LEARN SPRING SECURITY

Sort by:   newest | oldest | most voted
sanjeev kumar
Guest

Very nice article. Could you please share how to load properties files which are located in external directories and sub directories.
I tried
@PropertySource(value=”file:W:\myHome\Env\conf, W:\myHome\Env\conf\spring)
I am only providing the path & under that path are various properties file which I would like to load.

Also in application.properties I did this
spring.config.location=file:W:\myHome\Env\conf, W:\myHome\Env\conf\spring
But it is not working.
Could you please suggest.
Thank you

Grzegorz Piwowarek
Guest

It’s definitely possible. On your place, I would try to setup PropertySourcesPlaceholderConfigurer bean properly. Then it should be easy to access those properties

sanjeev kumar
Guest

Thank you. I tried this
@Bean
public static PropertySourcesPlaceholderConfigurer propertySources() {
PropertySourcesPlaceholderConfigurer ppConfig = new PropertySourcesPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[]
{ new ClassPathResource( “W:\myHome\Env\conf\spring” ) };
ppConfig.setLocations( resources );
return ppConfig;
}
Class path resource W:/myHome/Env/conf/spring cannot be opened because it does not exist. The path is correct.

Grzegorz Piwowarek
Guest

Try FileSystemResource instead of ClassPathResource. It’s not the classpath anymore 🙂

Colin Ma
Guest

hey Grrzegorz I have a property in my property file. The property is:
a.b.c;

In my property class I have

@RefreshScope
@Configuration
@ConfigurationProperties(prefix = “a”)

According to the article, because of relaxed binding I should be able to do something like:

private Sting aB; //or a_b

I then set up getters and setters, but it’s not being read in at all as expected. I have other properties such as a.d and a.e that are being read in properly, so I know the initial set up is correct.

Any idea what might be the issue?

Grzegorz Piwowarek
Guest

If you have a property “a.b.c”, it expects some nested object “b” to be there (and have a field “c” in it). Just like with theCredentials credentialsat the end of the section 2.

Try using a properties entry of “a.b” and defining a field

private String b;

Colin Ma
Guest

if I do have the private String b how do i access the .c?

Grzegorz Piwowarek
Guest

In this case, you can’t. It needs to be an object that has a field “c”.

Revisit section 2, there you have a property entry:
mail.credentials.username=john

and it works only because there is a Credentials object that has a field “username”.

In other words, your example would work if you had a field:
private MyCustomObject b;
And MyCustomObject would need to have a field “c”.

Srinivas T
Guest
Is it possible to use @ConfigurationProperties in non boot applications? I have following scenario: – I have developed a framework jar module for Mongo db persistence, this framwork is responsible to connect to DB and provides api’s to the clients. In this framework I have configuration object which has the Mongo DB connection and other details. I have used @Value annotation to load the properties from client application (Non boot application) configuration (Actual parent application which uses framework jar) and everything works fine. – Now I want to use this same framework jar with Spring boot application where I will… Read more »
Grzegorz Piwowarek
Guest

Well, @ConfigurationProperties comes from the boot package so if you do not have a Boot on your classpath, it should not be there. So how come can you use it in a non-boot application?

The scenario you are describing is tricky but it should be doable – check the YamlPropertiesFactoryBean class. Maybe you could try using for loading properties using the “oldschool” Spring way? In this case, it would work in boot and non-boot environments

sirine beji
Guest

I need to externalize the parameters set in my application.properties using environmental variables. This is my application.properties file:

spring.datasource.url= jdbc:mysql://${MYSQL_URL}:${MYSQL_PORT}/${MYSQL_DBNAME}
spring.datasource.username= ${MYSQL_USERNAME}
spring.datasource.password= ${MYSQL_PASSWORD}
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.jpa.hibernate.ddl-auto= update
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect
And those ${—} are Environmental Variables. But when I try to run my application I get this error:

Property: spring.datasource.url
Value: jdbc:mysql://${MYSQL_URL}:${MYSQL_PORT}/${MYSQL_DBNAME}
Origin: class path resource [application.properties]:1:24
Reason: Could not resolve placeholder ‘MYSQL_URL’ in value “jdbc:mysql://${MYSQL_URL}:

Grzegorz Piwowarek
Guest

You do not need to bind them to a properties file. You can simply inject them directly using @Value(“${MYSQL_USERNAME}”)

wpDiscuz