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

References

Leave a Reply

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