Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

A group of settings in a record

The @Value annotation is handy for one or two settings. When there are more, the ${...} strings spread across the code, and a typo in a name is easy to miss. The @ConfigurationProperties annotation collects all settings with a common prefix into one object — usually a record.

A record with settings

// src/main/java/com/example/blog/BlogProperties.java
package com.example.blog;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
 
@ConfigurationProperties("blog")
public record BlogProperties(
        String title,
        @DefaultValue("10") int pageSize) {
}

The blog prefix means: the title component comes from blog.title, and pageSize from blog.page-size. Spring matches pageSize in code with page-size in the file by itself. @DefaultValue sets the value when the setting is missing.

Values in the file

# src/main/resources/application.yaml
blog:
  title: Anna and Oleg blog
  page-size: 20

Spring turns 20 into an int itself. It can also parse lists, durations like 30s and sizes like 10MB.

Registration

For Spring to find such records, add @ConfigurationPropertiesScan to the main class:

// src/main/java/com/example/blog/BlogApplication.java
package com.example.blog;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
 
@SpringBootApplication
@ConfigurationPropertiesScan
public class BlogApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(BlogApplication.class, args);
    }
}

Now BlogProperties is an ordinary bean that you can receive in a constructor.

Using it

Let's limit the length of the post list with the page-size setting:

// src/main/java/com/example/blog/PostService.java
@Service
public class PostService {
 
    private final PostRepository repository;
    private final Clock clock;
    private final BlogProperties properties;
 
    public PostService(PostRepository repository, Clock clock, BlogProperties properties) {
        this.repository = repository;
        this.clock = clock;
        this.properties = properties;
    }
 
    public List<Post> findAll() {
        return repository.findAll().stream()
                .sorted(Comparator.comparing(Post::id))
                .limit(properties.pageSize())
                .toList();
    }
 
    // create() — as in the dependency injection lesson
}

findAll() returns posts in id order, but no more than 20. To change the number, edit application.yaml or set the environment variable BLOG_PAGE_SIZE=5 — no code changes needed.

@Value or a record

WhenWhat to choose
One setting in one place@Value
Several related settingsA record with @ConfigurationProperties
A setting needed in several classesA record: the name is written once

Common mistake

If a value cannot be turned into the needed type, the application does not start and says exactly where the problem is:

Failed to bind properties under 'blog.page-size' to int:
 
    Property: blog.page-size
    Value: "abc"
    Origin: "blog.page-size" from property source "commandLineArgs"
    Reason: failed to convert java.lang.String to @org.springframework.boot.context.properties.bind.DefaultValue int (caused by java.lang.NumberFormatException: For input string: "abc")

The Origin line shows where the wrong value came from — here the command-line argument --blog.page-size=abc.

Thanks for reading!

Donate to the site — we work hard for you.