[← When @Value wins](06-when-value-still-wins.md) · [Index](../README.md) · [Diagnosing a value →](08-diagnosing-a-value.md) # 7. IDE metadata, and the JDK 23 change that silently breaks it Transcript: [`05-metadata-generation.txt`](output/05-metadata-generation.txt). ## What the metadata is `spring-boot-configuration-processor` is an annotation processor. At compile time it reads your `@ConfigurationProperties` types and writes `META-INF/spring-configuration-metadata.json`: ```json { "groups": [ { "name": "demo.mail", "type": "com.ankurm.configprops.props.MailProperties" } ], "properties": [ { "name": "demo.mail.port", "type": "java.lang.Integer", "defaultValue": 587 } ] } ``` That file is what makes property names auto-complete in an IDE, and what shows the Javadoc on a record component as hover documentation. Nothing at runtime reads it. ## The failure Declaring the processor as a dependency — the way every tutorial written before 2024 shows — stops working on JDK 23 and later: ```xml org.springframework.boot spring-boot-configuration-processor true ``` Absent any processor-related command-line option, `-proc:none` is now javac's default. JDK 21 began printing an informative message when implicit annotation processing was detected, and JDK 23 turned the policy off, with the stated goal of making builds robust against processors landing on the classpath unintentionally. A processor that is only on the classpath is now simply not run. The build still succeeds. The jar is still valid. The application behaves identically. The only symptom is that property auto-completion quietly stops working, which is the kind of thing people blame on the IDE. Two compilations of identical sources with the identical processor jar: ``` A) javac -cp :spring-boot-configuration-processor.jar -d a $SOURCES spring-configuration-metadata.json files produced: 0 B) javac -proc:full -cp :spring-boot-configuration-processor.jar -d b $SOURCES spring-configuration-metadata.json files produced: 1 ``` ## The fix Declare it as an annotation processor path. That makes Maven pass `--processor-path`, and an explicit processor option re-enables processing -- the new default only applies when javac is given nothing to go on: ```xml org.apache.maven.plugins maven-compiler-plugin org.springframework.boot spring-boot-configuration-processor ${project.parent.version} ``` `-proc:full` also works and is a smaller change, but it restores the old policy for every processor on the classpath, which is the behaviour that was turned off for a reason. ## Checking `ls target/classes/META-INF/spring-configuration-metadata.json`. If it is not there, the processor did not run. Add `@ConfigurationProperties` metadata to your build's definition of done, because nothing else will tell you.