Reading Nested Properties in Spring Boot

A guide on How to read nested properties configurations in Spring Boot using @ConfigurationProperties.

Overview

Spring Boot @ConfigurationProperties annotation provides an easy way to read and bind application configurations from a properties or a yaml file into a Plain Old Java Object – POJO.

In this tutorial, we will focus on the different ways of reading Nested Application Properties using @ConfigurationProperties annotation of Spring Boot. If you are looking for reading a Simple Properties or yaml file or examples of using prefix attribute of @ConfigurationPropertis, we recommend reading Using @ConfigurationProperties in Spring Boot.

Nested Application Properties

In an application the properties or yaml files are useful for externalizing application configurations. That helps changing the configurations without modifying source files. Spring Boot provides a flexible way of externalizing configurations and binding the configurations into a Java POJO, upon startup.

In a properties or a yaml file, we often group related configurations under a common prefix. Such groups can also contain nested subgroups of configurations.

login-service: login-url: https://login.example.com username: login_user password: password123 header: auth_token: TOKEN content: C_TYPE user-service: url: https://users.example.com username: user_name password: strong-password
Code language: YAML (yaml)

Consider the above yaml configuration where we have two totally separate groups of properties. Let’s see examples of reading these groups of properties using Static Inner classes or creating creating dedicated properties classes for them.

@ConfigurationProperties using Dedicated Classes

Looking at the properties above we can figure out three groups of properties – User Service Properties, Login Service Properties and Header properties – nested under login service properties. Let’s model this properties structure by creating dedicated Properties beans.

First is the the bean to hold User Service Properties – Let’s call it UserProperties:

public class UserProperties { private String url; private String username; private String password; // Constructor, Getter and Setter Methods }
Code language: Java (java)

Note, that we haven’t marked this class with @ConfigurationProperties, because it is not required.

Next, we will create a class to bind the header properties, which are nested under login service.

public class LoginHeaderProperties { private String authToken; private String content; // Constructor, Getter and Setter Methods }
Code language: Java (java)

Now, let’s create LoginProperties to bind login-service properties.

public class LoginProperties { private String loginUrl; private String username; private String password; private LoginHeaderProperties header; // Constructor, Getter and Setter Methods }
Code language: Java (java)

Note that it has a reference to the Header Properties and the field name is in accordance with the nested property prefix.

Lastly, we will create our @ConfigurationProperties class that holds the reference to both of our main properties groups.

@Configuration @ConfigurationProperties public class NestedProperties { private LoginProperties loginService; private UserProperties userService; // Constructor, Getter and Setter Methods // ToString method }
Code language: Java (java)

We’ll also add a well formatted toString() implementation to print all the nested fields and their values. We will use it to print the populated beans once the application starts.

Our, classes structure, now exactly models the properties file. Let’s start the application and print the NestedProperties instance.

* Nested Properties
loginService: 
	loginUrl: https://login.example.com
	username: login_user
	password: password123
	header: 
		authToken: TOKEN
		content: C_TYPE
userService: 
	url: https://users.example.com
	username: user_name
	password: strong-password

We can see, we have correctly bound the nested application yaml (or a properties) file into our relational class structure.

@ConfigurationProperties using Nested Inner Classes

The previous way of binding nested properties using @ConfigurationProperties works. However, if there are too many groups and nesting levels, we will end up creating a bunch of classes to hold respective properties.

Alternatively, we can use nested inner classes to represent the properties sub-groups.

@Configuration @ConfigurationProperties public class NestedClassesProperties { private LoginProperties loginService; private UserProperties userService; // Constructor, Getter and Setter methods // ToString method public static class LoginProperties { private String loginUrl; private String username; private String password; private LoginHeaderProperties header; // Constructor, Getter and Setter methods public static class LoginHeaderProperties { private String authToken; private String content; // Constructor, Getter and Setter methods } } public static class UserProperties { private String url; private String username; private String password; // Constructor, Getter and Setter methods } }
Code language: Java (java)

Here, we have only one class and a several static inner classes, where each inner class represents a particular group of properties fields.

We have also added a well-formatted toString() method to print all of the properties upon startup.

* Nested Properties with Inner Classes
loginService: 
	loginUrl: https://login.example.com
	username: login_user
	password: password123
	header: 
		authToken: TOKEN
		content: C_TYPE
userService: 
	url: https://users.example.com
	username: user_name
	password: strong-password

We have printed the NestedClassesProperties instance using a @PostConstruct method and the output confirms that all of the nested properties are read correctly.

Summary

In this quick tutorial we learned to use Spring @ConfigurationProperties to map a nested properties file or a yaml file into Java Beans. We worked on a Spring Boot application having an application.yaml file with a nested sub groups of properties.

In the first example, we modelled the application configurations by creating multiple classes and used @ConfigurationProperties to read the nested properties. In the last example, instead of creating dedicated classes, we used static inner classes and achieved the same result.

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


Leave a Reply

Your email address will not be published. Required fields are marked *