In this article, we will show you how to use YAML instead of properties file in Spring Boot.
Tested with :
- Spring Boot 2.1.2.RELEASE
- Maven 3
- Snakeyaml:jar:1.23
In short, create a application.yml
in the src/resources
folder, Spring Boot will load and parse .yml
file automatically and bind the values into the classes which annotated with @ConfigurationProperties
P.S YAML files cannot be loaded by using the `@PropertySource`
1. YAML and Properties
application.yml
logging:
level:
org.springframework: ERROR
com.favtuts: DEBUG
spring:
profiles:
active: dev
main:
banner-mode: off
email: yaml@tuts.heomi.net
thread-pool: 10
wordpress:
menus:
- title: Home
name: Home
path: /
- title: About
name: About
path: /about
themes:
default-folder: /wp-content/themes/favtuts
servers:
- ip: 127.0.0.1
path: /dev1
- ip: 127.0.0.2
path: /dev2
- ip: 127.0.0.3
path: /dev3
Note:
The property spring.main.banner-mode=off
doesn’t work with YAML file (application.yml
). It throws following exception:
org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult ...... Failed to convert property value of type 'java.lang.Boolean' to required type 'org.springframework.boot.Banner$Mode'
The reason of above exception is; YAML treats ‘off’ value as boolean type, whereas Spring tries to convert it to the enum type Banner.Mode
.
Make sure it should be in application.yml:
main:
banner-mode: 'off'
NOT
main:
banner-mode: off
application.properties
# Spring Boot
logging.level.org.springframework=ERROR
logging.level.com.favtuts=DEBUG
spring.profiles.active=dev
spring.main.banner-mode=off
# Global
email=properties@tuts.heomi.net
thread-pool=10
# WordPress
wordpress.menus[0].title=Home
wordpress.menus[0].name=Home
wordpress.menus[0].path=/
wordpress.menus[1].title=About
wordpress.menus[1].name=About
wordpress.menus[1].path=/about
wordpress.themes.default-folder=/wp-content/themes/favtuts
wordpress.servers[0].ip=127.0.0.1
wordpress.servers[0].path=/dev1
wordpress.servers[1].ip=127.0.0.2
wordpress.servers[1].path=/dev2
wordpress.servers[2].ip=127.0.0.3
wordpress.servers[2].path=/dev3
2. Project Structure

3. Project Dependency
Spring Boot uses SnakeYAML library to parse the YAML file, and the SnakeYAML library is provided by spring-boot-starter
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-yaml-example</artifactId>
<packaging>jar</packaging>
<name>Spring Boot YAML Example</name>
<url>https://www.tuts.heomi.net</url>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
</plugin>
</plugins>
</build>
</project>
Project Dependencies :
$ mvn dependency:tree
+- org.springframework.boot:spring-boot-starter:jar:2.1.2.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot:jar:2.1.2.RELEASE:compile
[INFO] | | \- org.springframework:spring-context:jar:5.1.4.RELEASE:compile
[INFO] | | +- org.springframework:spring-aop:jar:5.1.4.RELEASE:compile
[INFO] | | +- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
[INFO] | | \- org.springframework:spring-expression:jar:5.1.4.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.RELEASE:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.2.RELEASE:compile
[INFO] | | +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] | | | \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile
[INFO] | | | \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile
[INFO] | | \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
[INFO] | +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] | +- org.springframework:spring-core:jar:5.1.4.RELEASE:compile
[INFO] | | \- org.springframework:spring-jcl:jar:5.1.4.RELEASE:compile
[INFO] | \- org.yaml:snakeyaml:jar:1.23:runtime <<------------- SnakeYAML
4. Spring Boot + YAML
4.1 Spring Boot will load and parse the YAML file and bind the values in the following @ConfigurationProperties
classes.
GlobalProperties.java
package com.favtuts.config; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties // no prefix, root level public class GlobalProperties { // thread-pool , relax binding private int threadPool; private String email; public int getThreadPool() { return threadPool; } public void setThreadPool(int threadPool) { this.threadPool = threadPool; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "GlobalProperties{" + "threadPool=" + threadPool + ", email='" + email + '\'' + '}'; } }
WordPressProperties.java
package com.favtuts.config; import java.util.ArrayList; import java.util.List; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import com.favtuts.config.model.Menu; import com.favtuts.config.model.Server; import com.favtuts.config.model.Theme; @Component @ConfigurationProperties("wordpress") public class WordPressProperties { private List<Menu> menus = new ArrayList<>(); private Theme themes; private List<Server> servers = new ArrayList<>(); public List<Menu> getMenus() { return menus; } public void setMenus(List<Menu> menus) { this.menus = menus; } public Theme getThemes() { return themes; } public void setThemes(Theme themes) { this.themes = themes; } public List<Server> getServers() { return servers; } public void setServers(List<Server> servers) { this.servers = servers; } @Override public String toString() { return "WordpressProperties{" + "menus=" + menus + ", themes=" + themes + ", servers=" + servers + '}'; } }
4.2 Model, nothing special, just some standard classes.
Menu.java
package com.favtuts.config.model; public class Menu { private String name; private String path; private String title; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Override public String toString() { return "Menu{" + "name='" + name + '\'' + ", path='" + path + '\'' + ", title='" + title + '\'' + '}'; } }
Server.java
package com.favtuts.config.model; public class Server { private String ip; private String path; public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } @Override public String toString() { return "Server{" + "ip='" + ip + '\'' + ", path='" + path + '\'' + '}'; } }
Theme.java
package com.favtuts.config.model; public class Theme { private String defaultFolder; public String getDefaultFolder() { return defaultFolder; } public void setDefaultFolder(String defaultFolder) { this.defaultFolder = defaultFolder; } @Override public String toString() { return "Theme{" + "defaultFolder='" + defaultFolder + '\'' + '}'; } }
4.3 Start a Spring Boot normally and print out the values.
Application.java
package com.favtuts; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import com.favtuts.config.GlobalProperties; import com.favtuts.config.WordpressProperties; @SpringBootApplication public class Application implements CommandLineRunner { @Autowired private WordPressProperties wpProperties; @Autowired private GlobalProperties globalProperties; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override public void run(String... args) { System.out.println(globalProperties); System.out.println(wpProperties); } }
5. DEMO
Package and run it.
# run spring boot directly
$ mvn spring-boot:run
# or package and run it
$ mvn package
$ java -jar target/spring-boot-yaml-example-1.0.jar
Output
GlobalProperties{
threadPool=10,
email='properties@tuts.heomi.net'
}
WordpressProperties{
menus=[
Menu{name='Home', path='/', title='Home'},
Menu{name='About', path='/about', title='About'}
],
themes=Theme{defaultFolder='/wp-content/themes/favtuts'},
servers=[
Server{ip='127.0.0.1', path='/dev1'},
Server{ip='127.0.0.2', path='/dev2'},
Server{ip='127.0.0.3', path='/dev3'}
]
}
YAML Multi-Profiles
Refer to this Spring Boot + Multiple Profiles YAML example
Download Source Code
$ git clone https://github.com/favtuts/java-spring-boot-tutorials.git
$ cd yaml-simple
$ mvn spring-boot:run