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: 20Spring 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
| When | What to choose |
|---|---|
| One setting in one place | @Value |
| Several related settings | A record with @ConfigurationProperties |
| A setting needed in several classes | A 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.