Skip to content

Omit version when annotation processor is managed by parent POM#7392

Merged
timtebeek merged 4 commits intomainfrom
tim/fix-issue-7384
Apr 16, 2026
Merged

Omit version when annotation processor is managed by parent POM#7392
timtebeek merged 4 commits intomainfrom
tim/fix-issue-7384

Conversation

@timtebeek
Copy link
Copy Markdown
Member

@timtebeek timtebeek commented Apr 16, 2026

Summary

  • AddAnnotationProcessor now checks ResolvedPom.getManagedVersion() before adding a new <path>; when the coordinate is already managed via effective <dependencyManagement> (e.g. inherited from spring-boot-starter-parent), the <version> is omitted so modern maven-compiler-plugin (3.12+) resolves it from dependencyManagement.
  • Added an idempotency guard so an existing versionless <path> entry is left untouched on subsequent runs.

Test plan

Modern `maven-compiler-plugin` (3.12+) resolves annotation processor
path versions from effective `dependencyManagement`. When the target
coordinate is already managed, adding a hardcoded `<version>` conflicts
with the parent POM's managed version (e.g. Spring Boot's).

Fixes #7384
Comment on lines +242 to +246
if (!child.getChildValue("version").isPresent()) {
// No explicit version: the path intentionally defers to
// the effective POM's dependencyManagement. Leave it alone.
return tg;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose I wasn't aware that the annotation processor paths could defer to the POM's dependencyManagement to begin with, as I've. generally only seen explicit versions in the past.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I only recently learned about this too. Maven Compiler Plugin 3.12+ falls back to effective <dependencyManagement> when a <path> has no version — see MCOMPILER-391.

Comment on lines -264 to +280
// Not found, so we add it
return tg.withContent(ListUtils.concat(tg.getChildren(), Xml.Tag.build(String.format(
"<path>\n<groupId>%s</groupId>\n<artifactId>%s</artifactId>\n<version>%s</version>\n</path>",
groupId, artifactId, version))));
// Not found, so we add it. Omit <version> when the effective POM's
// dependencyManagement already manages this coordinate — modern
// maven-compiler-plugin (3.12+) resolves annotation processor path
// versions from dependencyManagement automatically.
String managedVersion = currentMrr.getPom().getManagedVersion(groupId, artifactId, null, null);
String pathXml = managedVersion != null ?
String.format("<path>\n<groupId>%s</groupId>\n<artifactId>%s</artifactId>\n</path>",
groupId, artifactId) :
String.format("<path>\n<groupId>%s</groupId>\n<artifactId>%s</artifactId>\n<version>%s</version>\n</path>",
groupId, artifactId, version);
return tg.withContent(ListUtils.concat(tg.getChildren(), Xml.Tag.build(pathXml)));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does any of the logic need to be guarded by actually using maven-compiler-plugin 3.12+? If this ended up being called and they were on a lower version of the plugin than 3.12, might it not end up potentially adding the annotation processor path without a version tag, breaking compilation?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! I've just pushed a guard: compilerPluginSupportsManagedVersions() looks up the effective maven-compiler-plugin version from ResolvedPom.getPlugins() / getPluginManagement() and only omits <version> when it's >= 3.12.0. For older plugin versions (or when the version can't be determined), we still emit the explicit <version> as before. Added keepVersionWhenCompilerPluginIsOlderThan312 to pin that behavior.

Only maven-compiler-plugin 3.12.0 and newer resolve annotation processor
path versions from effective dependencyManagement. For older plugin
versions, a missing <version> would break compilation, so keep emitting
it explicitly.
@steve-aom-elliott
Copy link
Copy Markdown
Contributor

Going to try adding tests for just a few more scenarios shortly to add a bit more coverage.

Adds tests exercising three additional paths through the
compilerPluginSupportsManagedVersions guard that the existing pair of
tests (which inline the plugin version) does not reach:

- Property substitution: <version>${maven.compiler.plugin.version}</version>
- Same-POM <pluginManagement> supplies the version
- Parent-POM <pluginManagement> supplies the version (mirrors #7384)

Also adds a test for the conservative-false fallback when the compiler
plugin version cannot be determined anywhere in the effective POM.
@github-project-automation github-project-automation bot moved this from In Progress to Ready to Review in OpenRewrite Apr 16, 2026
@timtebeek timtebeek merged commit 285a721 into main Apr 16, 2026
1 check passed
@timtebeek timtebeek deleted the tim/fix-issue-7384 branch April 16, 2026 22:07
@github-project-automation github-project-automation bot moved this from Ready to Review to Done in OpenRewrite Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Lombok Plugin Version is added, even when managed by Spring Boot

2 participants