Spring Boot ConfigurationProperties tutorial

Novice programmers rarely see the value in externalized configuration. It's tedious and doesn't result in an immediate payoff. That means this task is often overlooked or done poorly, if at all.

For those who create applications and microservices with Spring Boot, however, the availability of configuration annotations and the application.properties file simplifies data externalization. With Spring Boot configuration tools, externalization is largely straightforward, which means that novice developers no longer have any excuses to eschew the responsibility of configuration-based best practices from the get-go.

Spring Boot @ConfigurationProperties example

To demonstrate how Spring Boot configuration works, we'll start with the creation of a Spring Starter Project with the Spring Tool Suite.

The sample project settings are as follows:

  • GroupId: com.mcnz.spring.configuration.example.
  • ArtifactId: spring-configuration-example.
  • Version: 1.0-SNAPSHOT.
  • Name: Spring Configuration Tutorial.
Spring Boot Starter Wizard.
Figure 1. Create a simple Spring Boot project with @ConfigurationProperties support.

Spring Boot's properties and YAML files

Spring Boot projects store their configuration data in a properties file. By convention, this Spring configuration file is placed in the resources folder of the project and named application.properties.

Optionally, a YAML-based Spring properties file is acceptable as well.

Spring properties in the resources folder.
Figure 2. Location of Spring Boot application.properties file.

Spring's application.properties file

To demonstrate how the application.properties Spring configuration file works with the Spring @ConfigurationProperties annotation, we fill the file with a variety of data types:

  • Basic String data.
  • A list of values.
  • A data map.
  • An inner class with properties.

The Spring Boot application.properties file with our added data looks as follows.

#Spring Boot configuration file example

# simple spring configurationd data
spring.boot.config.example.company = "Dreamix"
spring.boot.config.example.suite = 1113
spring.boot.config.example.active = true

# list data in spring configuration file
spring.boot.config.example.list[0] = "list-data-0"
spring.boot.config.example.list[1] = "list-data-1"

# simple map in a spring configuration file
spring.boot.config.example.map.key1="value1"
spring.boot.config.example.map.key2="value2"

# inner class in Spring config file
spring.boot.config.example.innerClass.property1 = "annotations"
spring.boot.config.example.innerClass.property2 = "xml"
spring.boot.config.example.innerClass.property3 = "YAML"

Spring Boot's @ConfigurationProperties annotation

The next step is to create a class that will be decorated with the Spring Boot @ConfigurationProperties and Spring @Component annotations. This class injects the properties defined in the properties file into instance variables at runtime.

We call the class that bears the Spring @ConfigurationProperties annotation SpringBootConfiguration.

package com.mcnz.spring.configuration;
import org.springframework.boot.context.properties.*;
import org.springframework.stereotype.*;

@ConfigurationProperties(prefix="spring.boot.config.example")
@Component
public class SpringBootConfiguration {

}

The prefix argument shows which properties, starting with this prefix, are to be used by the class decorated with the @ConfigurationProperties annotation.

Field injection with Spring's @ConfigurationProperties

Now it's time for the cool part.

To access the basic String properties defined in the Spring Boot configuration file, all you need to do is add a property with the name that matches one in the application.properties file, along with the corresponding setters and getters. The SpringBootConfiguration example class looks like this:

package com.mcnz.spring.configuration;

import org.springframework.boot.context.properties.*;
import org.springframework.stereotype.*;

@ConfigurationProperties(prefix="spring.boot.config.example")
@Component
public class SpringBootConfiguration {

	private String company;
	private int suite;
	private boolean active;

	public String getCompany() { return company; }
	public void setCompany(String c) { company = c; }
	public int getSuite() { return suite; }
	public void setSuite(int s) { suite = s; }
	public boolean isActive() { return active; }
	public void setActive(boolean a) { this.active = a; }
}

All we need to do to quickly test this in the @SpringBootApplication annotated class is as follows:

It looks as shown in Figure 3.

Accessing configuration properties in Spring Boot.
Figure 3. Accessing the data held by the @ConfigurationProperties annotated class.

As we expect, when the class runs, here is the output.

"Dreamix"
1113
true

Spring ConfigurationProperties with Lists and Maps

We can also convert the Map and List data defined in the Spring configuration file into Java objects. To do this, declare instances of the appropriate type in the code.

private Map<String, String> map;
private List<String> list;

public Map<String, String> getMap() {return map;}
public void setMap(Map<String, String> m) {map = m;}
public List<String> getList() {return list;}
public void setList(List<String> l) {list = l;}

A user can also declare an inner class within the configuration class, annotate it with @ConfigurationProperties and point the prefix attribute to the root name of the properties to be used. The Spring Boot configuration takes care of the rest.

@ConfigurationProperties(prefix="spring.boot.config.example")
@Component
public class SpringBootConfiguration {

	private final InnerClass innerClass = new InnerClass();

	public InnerClass getInnerClass() {
		return innerClass;
	}

	@ConfigurationProperties(prefix="innerClass")
	public class InnerClass {
		private String property1;
		private String property2;
		private String property3;
		public String getProperty1() {return property1;}
		public void setProperty1(String p) { property1 = p; }
		public String getProperty2() {return property2;}
		public void setProperty2(String p) { property2 = p; }
		public String getProperty3() {return property3;}
		public void setProperty3(String p) { property3 = p; }
	}

/* Previously coded properties getters and setters omitted */

}

When saved, the List, Map and InnerClass are all easily accessed anywhere the SpringConfigurationExampleApplication class is autowired.

Here is the complete SpringConfigurationExampleApplication with the configuration class autowired in.

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringConfigurationExampleApplication implements CommandLineRunner  {

	@Autowired
	SpringBootConfiguration config;

	public static void main(String[] args) {
		SpringApplication.run(SpringConfigurationExampleApplication.class, args);
	}

    @Override
    public void run(String... args) throws Exception {
        System.out.println(config.getCompany());
        System.out.println(config.getSuite());
        System.out.println(config.isActive());

        System.out.println(config.getList().get(0));
        System.out.println(config.getMap());
        System.out.println(config.getInnerClass().getProperty1());
    }

}

When the Spring configuration test class runs, the final output is observed.

ConfigurationProperties with maps, lists and inner classes.
Figure 4. Output from running the Spring Boot configuration class application.

Benefits of Spring's ConfigurationProperties

As an application matures and is regularly updated, we need a way to easily change the configurations that doesn't require hours to determine which property we changed and hunt for it in the code. Other benefits of an externalized configuration include the following:

  • Better organization of the project.
  • Better reliability.
  • Reduced costs and risks.
  • Easy refactoring.
  • Flexibility when testing.

Spring Boot's ability to externalize configuration makes it easy to define data in simple property files and subsequently access that data anywhere that the Spring Boot configuration class is autowired into your application.

The source code for this application is available on GitHub.

Editor's note: This article was originally published in July 2019 and has been updated for clarity and to improve reader experience.

Cameron McKenzie has been a Java EE software engineer for 20 years. His current specialties include Agile development; DevOps; Spring; and container-based technologies such as Docker, Swarm and Kubernetes.

View All Videos