A group of settings: @ConfigMapping
When there are many settings, separate fields with @ConfigProperty become awkward: key names are repeated as strings in different classes, and a typo is easy to miss. Config mapping solves this: you describe a group of settings with one interface, and Quarkus fills it with values from the file and checks them at startup. This is the recommended way to handle your own settings in Quarkus.
The settings interface
Create an interface in the application package:
// src/main/java/com/example/blog/BlogConfig.java
package com.example.blog;
import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
import java.util.Optional;
@ConfigMapping(prefix = "blog")
public interface BlogConfig {
String title();
@WithDefault("20")
int pageSize();
Optional<String> owner();
}prefix = "blog" binds the interface to the blog.* keys. Each method is one setting. The method name becomes the key automatically: pageSize() reads blog.page-size, title() reads blog.title.
| In the interface | What it means |
|---|---|
String title() | A required setting; without it the application does not start |
@WithDefault("20") | A default value |
Optional<String> owner() | An optional setting |
@WithName("page") | A custom key name instead of the method name |
Using it
The interface is injected like a normal bean. Let's rewrite InfoResource:
// src/main/java/com/example/blog/InfoResource.java
package com.example.blog;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@Path("/info")
public class InfoResource {
@Inject
BlogConfig config;
@GET
public String info() {
String owner = config.owner().orElse("unknown");
return config.title() + ", " + config.pageSize() + " posts per page, owner: " + owner;
}
}The application.properties file stays the same as in the previous lesson. In dev mode:
curl http://localhost:8080/infoAnna's blog (dev), 10 posts per page, owner: unknown
There is no blog.owner key in the file, so the Optional is empty. Add the line blog.owner=Anna, and after a refresh the answer ends with owner: Anna.
Nested groups
A method can return another interface, which gives a nested group:
// src/main/java/com/example/blog/BlogConfig.java
Comments comments();
interface Comments {
@WithDefault("true")
boolean enabled();
@WithDefault("1000")
int maxLength();
}These methods read the blog.comments.enabled and blog.comments.max-length keys.
The same bean anywhere
BlogConfig can be injected into a service, a resource or a scheduled job — the values are the same everywhere. In the lesson on database queries we take the page size for the post list from it.
Common mistake
Config mapping checks not only missing keys but also unknown ones. If the file has a typo, for example blog.titel=Typo, the application does not start:
SRCFG00050: blog.titel in PropertiesConfigSource[source=file:/.../target/classes/application.properties]:4 does not map to any root
The message names the key and the line number in the file. This is one of the main advantages of @ConfigMapping over @ConfigProperty: with separate fields a typo in a key name would silently turn into the default value.