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 | |
---|---|
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
).