24.6 Using YAML instead of Properties

YAML is a superset of JSON, and as such is a very convenient format for specifying hierarchical configuration data. The SpringApplication class will automatically support YAML as an alternative to properties whenever you have the SnakeYAML library on your classpath.

[Note] Note
If you use ‘Starters’ SnakeYAML will be automatically provided via spring-boot-starter.

24.6.1 Loading YAML

Spring Framework provides two convenient classes that can be used to load YAML documents. The YamlPropertiesFactoryBean will load YAML as Properties and the YamlMapFactoryBean will load YAML as a Map.

For example, the following YAML document:

environments:
 dev:
 url: http://dev.bar.com
 name: Developer Setup
 prod:
 url: http://foo.bar.com
 name: My Cool App

Would be transformed into these properties:

environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App

YAML lists are represented as property keys with [index] dereferencers, for example this YAML:

my:
 servers:
       - dev.bar.com
       - foo.bar.com

Would be transformed into these properties:

my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

To bind to properties like that using the Spring DataBinder utilities (which is what @ConfigurationProperties does) you need to have a property in the target bean of type java.util.List (or Set) and you either need to provide a setter, or initialize it with a mutable value, e.g. this will bind to the properties above

_@ConfigurationProperties(prefix="my")_
public class Config {

    private List<String> servers = new ArrayList<String>();

    public List<String> getServers() {
        return this.servers;
    }
}

24.6.2 Exposing YAML as properties in the Spring Environment

The YamlPropertySourceLoader class can be used to expose YAML as a PropertySource in the Spring Environment. This allows you to use the familiar @Value annotation with placeholders syntax to access YAML properties.

24.6.3 Multi-profile YAML documents

You can specify multiple profile-specific YAML documents in a single file by using a spring.profiles key to indicate when the document applies. For example:

server:
 address: 192.168.1.100
---
spring:
 profiles: development
server:
 address: 127.0.0.1
---
spring:
 profiles: production
server:
 address: 192.168.1.120

In the example above, the server.address property will be 127.0.0.1 if the development profile is active. If the development and production profiles are not enabled, then the value for the property will be 192.168.1.100.

The default profiles are activated if none are explicitly active when the application context starts. So in this YAML we set a value for security.user.password that is only available in the "default" profile:

server:
 port: 8000
---
spring:
 profiles: default
security:
 user:
 password: weak

whereas in this example, the password is always set because it isn’t attached to any profile, and it would have to be explicitly reset in all other profiles as necessary:

server:
 port: 8000
security:
 user:
 password: weak

Spring profiles designated using the "spring.profiles" element may optionally be negated using the ! character. If both negated and non-negated profiles are specified for a single document, at least one non-negated profile must match and no negated profiles may match.

24.6.4 YAML shortcomings

YAML files can’t be loaded via the @PropertySource annotation. So in the case that you need to load values that way, you need to use a properties file.

24.6.5 Merging YAML lists

As we have seen above, any YAML content is ultimately transformed to properties. That process may be counter intuitive when overriding “list” properties via a profile.

For example, assume a MyPojo object with name and description attributes that are null by default. Let’s expose a list of MyPojo from FooProperties:

_@ConfigurationProperties("foo")_
public class FooProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}

Consider the following configuration:

foo:
 list:
 - name: my name
 description: my description
---
spring:
 profiles: dev
foo:
 list:
 - name: my another name

If the dev profile isn’t active, FooProperties.list will contain one MyPojo entry as defined above. If the dev profile is enabled however, the list will still only contain one entry (with name “my another name” and description null). This configuration will not add a second MyPojo instance to the list, and it won’t merge the items.

When a collection is specified in multiple profiles, the one with highest priority is used (and only that one):

foo:
 list:
 - name: my name
 description: my description
 - name: another name
 description: another description
---
spring:
 profiles: dev
foo:
 list:
 - name: my another name

In the example above, considering that the dev profile is active, FooProperties.list will contain one MyPojo entry (with name “my another name” and description null).

results matching ""

    No results matching ""