skip to content

Configuration property metadata

The configuration processor generates metadata that gives your own @ConfigurationProperties auto-completion, documentation and deprecation hints in an IDE. A small but telling detail when the role involves building libraries for other teams.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What is the spring-boot-configuration-processor, and what does adding it to your build produce?

level: juniorimportance: must knowfreq 55%

answer

  1. Compile-time annotation processor
  2. Generates spring-configuration-metadata.json
  3. Powers IDE auto-completion for @ConfigurationProperties
  4. Optional dependency, no runtime effect
  5. Descriptions come from Javadoc

basics

~10 s

It is a compile-time annotation processor. When you add it as a dependency, it scans your @ConfigurationProperties classes during compilation and generates META-INF/spring-configuration-metadata.json, which IDEs read to give auto-completion and docs for your properties.

solid answer

~40 s

spring-boot-configuration-processor is a Java annotation processor you add on the annotationProcessor path (or kapt for Kotlin). At compile time it finds @ConfigurationProperties classes plus @Bean methods annotated with them, and emits META-INF/spring-configuration-metadata.json into the build output. That JSON describes each property: its full name, type, default value, description (pulled from the field/getter Javadoc), and which group it belongs to. IDEs like IntelliJ and VS Code consume this file to offer auto-completion, type checking, and hover documentation when you edit application.properties or application.yml. It is purely tooling metadata generated at build time; it has no effect on how properties bind or behave at runtime. The dependency is marked optional so it never ships in your runtime classpath.

code

java · 21 lines
java
@ConfigurationProperties(prefix = "app.mail")
public class MailProperties {

    /**
     * SMTP server host to connect to.
     */
    private String host = "localhost";

    /**
     * SMTP server port.
     */
    private int port = 25;

    // getters/setters let the processor detect these properties
    public String getHost() { return host; }
    public void setHost(String host) { this.host = host; }
    public int getPort() { return port; }
    public void setPort(int port) { this.port = port; }
}
// -> generates entries for app.mail.host (default "localhost")
//    and app.mail.port (default 25) in spring-configuration-metadata.json

go deeper

for a junior

Know it is a compile-time processor that produces spring-configuration-metadata.json for IDE auto-completion.

for a middle

Explain how properties/groups are detected (getters, constructor binding) and that descriptions come from Javadoc.

for a senior

Discuss the optional/compile-only nature, Kotlin/kapt, and that it has zero runtime impact.

for a principal

Frame it as developer-experience tooling; reason about module boundaries, when metadata regenerates, and self-documenting config as a team practice.

## What it is `spring-boot-configuration-processor` is a **Java annotation processor** (a plug-in that runs inside `javac` during compilation). Its single job is to inspect your `@ConfigurationProperties`-annotated classes and write a machine-readable description of every configuration property your application exposes. ## What it generates The output is a file at `META-INF/spring-configuration-metadata.json` in your compiled output (e.g. `build/classes/.../META-INF/` or `target/classes/META-INF/`). It contains up to three top-level arrays: - **`groups`** — one entry per `@ConfigurationProperties` class (and per `@Bean` method that returns such a type). A group is a namespace like `app.mail`. - **`properties`** — the flattened, individual keys such as `app.mail.host`, each with `name`, `type` (fully-qualified Java type), optional `defaultValue`, `description`, and the `sourceType` that declared it. - **`hints`** — extra auto-completion assistance (usually supplied manually; see the additional-metadata question). ## Where descriptions come from The processor extracts the **Javadoc comment** on the field (or getter) and uses it as the property `description`. So documenting your properties with plain Javadoc directly improves the IDE experience. Default values for simple types (numbers, booleans, strings, enums) are read from the field initializer. ## How to add it Gradle: ```groovy annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' ``` Maven (Spring Boot manages the version and marks it optional): ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> ``` For **Kotlin** you must run it through **kapt** (`kapt "org.springframework.boot:spring-boot-configuration-processor"`), because Kotlin classes are not compiled by `javac`. ## Key facts / gotchas - It is **compile-time only** and **optional** — it is never on the runtime classpath and does **not** affect binding, validation, or relaxed-name matching at runtime. Removing it changes nothing about how the app runs; it only removes IDE assistance. - The processor detects properties via **getters/setters** or **constructor binding** (records, `@ConstructorBinding`). A field with no getter and no constructor parameter may not appear. - Nested types that are not inner classes need `@NestedConfigurationProperty` on the field to be included. - If you add a property but the IDE does not offer it, you usually need a **rebuild**, because the JSON is only regenerated when the annotated sources are recompiled. ## When to use Always add it in any module that declares `@ConfigurationProperties`. It costs nothing at runtime and gives your team (and future you) discoverable, self-documenting configuration.

  • Does removing the configuration-processor break your application at runtime?
    No. It only generates IDE metadata at compile time. Property binding at runtime is done by Spring Boot's Binder using reflection, independent of the JSON file, so the app runs identically without it.
  • Why does the processor need getters/setters or a binding constructor?
    It discovers properties by inspecting the accessor/mutator or constructor parameters that define the bindable surface. A bare private field with no getter and no constructor binding gives it nothing to reflect on, so that property is omitted from the metadata.

saying these in an interview costs you the question

  • Claiming the processor is required at runtime for property binding to work
  • Thinking it must ship in the production jar
  • Believing it works for Kotlin without kapt
  • Saying it reads application.yml to generate metadata (it reads source classes, not config files)

context

open as a page

What is additional-spring-configuration-metadata.json and when do you need it?

level: middleimportance: should knowfreq 40%

basics

~10 s

It is a hand-written file in src/main/resources/META-INF/ where you add metadata the processor cannot infer — like value hints, descriptions, or deprecations. At compile time the processor merges it into the generated spring-configuration-metadata.json.

open as a page

How do you mark a @ConfigurationProperties property as deprecated in the metadata, and what do the deprecation levels mean?

level: middleimportance: should knowfreq 30%

basics

~20 s

Annotate the getter with @DeprecatedConfigurationProperty(reason, replacement) and the processor emits a deprecation entry, so the IDE warns users. You can also declare it manually in additional-spring-configuration-metadata.json with a deprecation block having level warning or error.

open as a page

How do value hints and hint providers work in configuration metadata, including hints for Map keys and values?

level: seniorimportance: should knowfreq 28%

basics

~20 s

A hint entry links to a property by name and supplies either a static list of suggested values or a provider that computes suggestions dynamically (e.g. class-reference, logger-name, handle-as). For maps you target property.keys or property.values.

open as a page

A team's @ConfigurationProperties keys aren't showing up in IDE auto-completion. Walk through the likely causes, including Kotlin and incremental-build pitfalls.

level: principalimportance: nice to knowfreq 22%

basics

~10 s

Check that the configuration-processor is on the annotation-processor path (kapt for Kotlin), that properties have getters/setters or constructor binding, that nested non-inner types use @NestedConfigurationProperty, and that the project was rebuilt so spring-configuration-metadata.json regenerated.

open as a page