JDK-8321319 will disable the automatic execution of annotation processors that are present on the classpath in Java 23+, because of supply chain attack concerns.

This would for instance mean that just adding spring-boot-configuration-processor as a dependency won't do anything until the annotation processor in that artifact is explicitly allowed to run.

I think Spring Boot will need to respond to this change in one way or another, either by documenting how users can deal with this (e.g. maven-compiler-plugin's annotationProcessorPaths, using maven-processor-plugin, or dropping this protection again by setting -proc:full while that's still available) or by configuring javac to execute Spring's (or all?) annotation processors automatically.

Comment From: wilkinsona

Thanks for the suggestion. I think this should, at most, be addressed by Spring Boot with some documentation updates. I don't think we should set -proc:full by default as that would undo the intent of the change in the JDK. Gradle users are unaffected as using the annotationProcessor configuration to declare the dependency is all that's necessary and this is covered by the existing documentation.

Some updates could be made to:

  • https://docs.spring.io/spring-boot/reference/features/developing-auto-configuration.html#features.developing-auto-configuration.custom-starter.autoconfigure-module
  • https://docs.spring.io/spring-boot/specification/configuration-metadata/annotation-processor.html#appendix.configuration-metadata.annotation-processor.configuring

We can either duplicate the content, or we could consider adding a new section on annotation processor configuration to which the above sections could cross-link.

Before we do anything, I'd like to double-check with the rest of the team if, given it's a general Maven with Java 23+ problem, it is something we want to cover in Boot's docs.

Comment From: wilkinsona

Thanks to this change in the Maven compiler plugin, it looks like our best option here is to document that annotation processors be declared using <annotationProcessorPaths>. You no longer need to specify a version so I think this is better overall as it makes the intent of the dependency clearer (similar to Gradle's annotationProcessor configuration). An added bonus is that this will, I believe, enable annotation processing with Java 23+ as well. It requires 3.12.0+ of the compiler plugin.

Comment From: breun

Maybe Spring Boot could provide a default <annotationProcessorPaths> configuration for maven-compiler-plugin (maybe only activated when Java 23+ is used?) with all artifacts that are managed by Spring Boot and contain annotation processors?

That might still require documentation to explain how to allow additional artifacts to execute their annotation processors, because a user specifying <annotationProcessorPaths> would override Spring Boot's default list of allowed artifacts. I think Maven's combine.children="append" could be used to let Spring Boot users allow additional artifacts.

Comment From: wilkinsona

Thanks for the suggestion, but I don't think we should do that. Boot's annotation processors are currently an opt-in feature and I think that should remain the case. All that should change here is the recommended way to opt in when using Maven.

Comment From: cachescrubber

I think besides the spring-boot documentation, start.spring.io would be an adequate place to generate a pom.xml with maven-compiler-plugin's annotationProcessorPaths pre configured for the spring-boot-configuration-processor. The same would apply to Lombok, IMO.

Comment From: breun

Configuring <annotationProcessorPaths> for maven-compiler-plugin looks like the easiest way to allow annotation processors, but it provides only artifact-level granularity and by default executes all annotation processors in the the artifact, as well as all annotation processors in transitive dependencies of the artifact. I guess that is why the supply chain attack article that sparked this change recommends explicitly listing the allowed annotation processors. The article provides an example based on org.bsc.maven:maven-processor-plugin, but I believe the same could be achieved via <annotationProcessors> with maven-compiler-plugin.

Comment From: breun

I've experimented a bit in one of my own Maven multi-module projects which uses Java 21, and in that scenario I found a downside to using maven-compiler-plugin's <annotationProcessors> to explicitly list all individual annotation processors that should be executed, because to secure the project against attacks via this vector you need to set -proc:none via <compilerArgs> in the root module, but you need to override that flag in child modules that do need to execute annotation processors. You can override <compilerArgs> in child POMs, but that means that any other default compiler flags (e.g. something like -Xlint:all or -parameters) also don't get inherited and need to be specified again.

I found that for that reason it's nicer to execute annotation processors via maven-processor-plugin in a separate phase (typically generate-sources or generate-resources), like the attack article showed, because that allows setting -proc:none in the root POM and then doesn't require any maven-compiler-plugin configuration overrides in child POMs.

On a Java version that doesn't execute all detected annotation processors by default anyway, this might not be an issue, because then you don't need to set -proc:none and thus you also won't need to override it in child POMs.