Spring Boot Recipe: Reading and Validating Lists of Configuration Properties

In one of my Spring Boot microservices, I want to keep track of a list of servers that can be externally configurable.

I can have zero to infinity servers, so I want my application to allow me to easily define this.

I also want to be able to check that the configuration is correct, so I don’t accidentally forget to enter a url or a name for my server.

In this post, I will show you how you can use the Spring ConfigurationProperties to organize and validate a map of configuration values.

Defining the format in Application.yml

We’ll start with how our definition looks in our src/main/resources/application.yml file:

myapp:
  servers:
    - 
      name: 'server1'
      url: 'http://www.server1.com'
    -
      name: 'server2'
      url: 'http://www.server2.com'

In this file, we’re defining two servers. You will notice that there is a ‘-‘ before each of the server definitions. This is the YML way of saying that the servers we have defined is a list of objects. Spring Boot will essentially flatten this definition into a structure of the format myapp.servers[0].name == ‘server1’ and myapp.servers[1].name == ‘server2’.

Reading the Configuration

We then need to create an object that will capture this yml definition into something we can use in our project. We will use the Spring Boot ConfigurationProperties annotation to map our yml file to an actual List of servers.

The code for this looks as follows:

@Configuration
@ConfigurationProperties(prefix = 'myapp') // (1)
class ServerProperties { 
    @Valid 
    List servers // (2)

    static class Server { // (3)
        @NotEmpty
        String name       

        @NotEmpty
        String url
    }
}

In (1), we map our properties file to capture the configuration path for myapp.*

In (2), we define a servers property that will hold the list of the servers that our application needs.

In (3), we create a class that will represent our server definition.

The @NotEmpty and @Valid annotations are Hibernate and Javax validation constraints that will ensure that the properties we have defined exists and meet a certain criteria. The @Valid annotation on the List makes sure that when we validate our ServerProperties, the validation will go into each server definition and validates it.

One thing to point out is that Spring Boot will freak out if the class of Server (3) is not static.

Accessing the Properties

In another bean, we can now use the properties we have defined.

For example, let’s say we want to have another bean that will create RESTClient definitions for each of the server we have added in our configuration.

class ServerClientConfig {
    @Bean
    Map serverClients(@Valid ServerProperties serverProps) {
        serverProps.servers.collectEntries(){ server ->
            ["${server.name}" : createClient( server.url )]
        }
    }

    // createClient() ... 
}

All we need to do here is to add the @Valid ServerProperties serverProps property into our bean definition. The @Valid annotation will trigger the validation requirements and will throw an exception if the application.yml file is misformed.

6 thoughts on “Spring Boot Recipe: Reading and Validating Lists of Configuration Properties

  1. nisusc

    Is it possible to specify these properties in application.properties instead of application.yml ?
    Unfortunately, it could not make it work with application.properties.

    Reply
    1. Mashrur Mia

      Yes it is possible and I’ve just tried it. So something like the following need to be setup in the application.properties

      myapp.servers[0].name == ‘server1′

      myapp.servers[1].name == ‘server2′.
      ..

      Reply
  2. anoop

    I tried the approach provided here… but I run into the below exception..
    IllegalAccessException: Class org.springframework.beans.BeanWrapperImpl can not access a member of class prop.DummyProperties$Server with modifiers “”

    below is my class… its basically the same class as given here.. with just package/name change and getters/setters
    package prop;

    import java.util.ArrayList;
    import java.util.List;

    import javax.validation.constraints.NotNull;

    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;

    @ConfigurationProperties(prefix = “myapp”)
    @Component
    public class DummyProperties {
    List servers = new ArrayList();
    public List getServers() {
    return servers;
    }
    public void setServers(List servers) {
    this.servers = servers;
    }

    static class Server {
    @NotNull
    private String name;
    @NotNull
    private String url;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getUrl() {
    return url;
    }
    public void setUrl(String url) {
    this.url = url;
    }
    }
    }

    Reply
  3. anoop

    Figured it out. The nested class has to be public.. Its funny given that the Spring documentation gives an example where its private…

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s