Skip to content

Retain javax.xml.bind:jaxb-api when jackson-module-jaxb-annotations is present#987

Merged
timtebeek merged 5 commits intomainfrom
retain-jaxb-api-for-jackson
Feb 17, 2026
Merged

Retain javax.xml.bind:jaxb-api when jackson-module-jaxb-annotations is present#987
timtebeek merged 5 commits intomainfrom
retain-jaxb-api-for-jackson

Conversation

@Jenson3210
Copy link
Contributor

@Jenson3210 Jenson3210 commented Feb 17, 2026

Summary

  • Adds RetainJaxbApiForJackson recipe that re-adds javax.xml.bind:jaxb-api as a runtime dependency when jackson-module-jaxb-annotations is on the classpath
  • Wires the recipe into JavaxXmlBindMigrationToJakartaXmlBind in jakarta-ee-9.yml, after the ChangeDependency step
  • Adds tests for both Gradle and Maven, plus a negative test when Jackson is not present

Problem

When running the Jakarta EE 9 migration (JavaxXmlBindMigrationToJakartaXmlBind), ChangeDependency replaces javax.xml.bind:jaxb-api with jakarta.xml.bind:jakarta.xml.bind-api:3.0.x. However, jackson-module-jaxb-annotations transitively depends on jakarta.xml.bind:jakarta.xml.bind-api:2.3.x (the bridge version that still provides the javax.xml.bind namespace). Version resolution picks the highest version (3.0.x), which no longer provides javax.xml.bind classes, causing NoClassDefFoundError at runtime.

Solution

A new imperative recipe RetainJaxbApiForJackson checks if jackson-module-jaxb-annotations is on the resolved classpath (for both Gradle and Maven). If found, it adds javax.xml.bind:jaxb-api:2.3.x as a runtimeOnly/runtime dependency so the javax namespace classes remain available.

Test plan

…s present

When migrating from javax.xml.bind to jakarta.xml.bind 3.0+, the
ChangeDependency recipe replaces javax.xml.bind:jaxb-api entirely.
However, jackson-module-jaxb-annotations still depends on the
javax.xml.bind namespace at runtime through its transitive dependency
on jakarta.xml.bind:jakarta.xml.bind-api:2.3.x (the bridge version).
When version resolution upgrades to 3.0.x+, the javax.xml.bind classes
disappear, causing NoClassDefFoundError.

This adds a RetainJaxbApiForJackson recipe that re-adds
javax.xml.bind:jaxb-api as a runtime dependency when
jackson-module-jaxb-annotations is detected on the classpath,
for both Gradle and Maven projects.

Fixes #504
@Jenson3210 Jenson3210 requested a review from timtebeek February 17, 2026 11:03
Address PR feedback:
- Replace imperative RetainJaxbApiForJackson.java with declarative YAML
  recipes using FindDependency preconditions (split into Gradle and Maven
  variants since ModuleHasDependency is a ScanningRecipe which doesn't
  work as a declarative precondition)
- Use assertThat().actual() instead of return in test assertions
…econdition

Replace the Gradle/Maven split with a single declarative recipe that uses
DependencyInsight as a cross-platform precondition instead of build-system
specific FindDependency recipes.
@github-project-automation github-project-automation bot moved this from In Progress to Ready to Review in OpenRewrite Feb 17, 2026
@timtebeek timtebeek merged commit 56b280c into main Feb 17, 2026
1 check passed
@github-project-automation github-project-automation bot moved this from Ready to Review to Done in OpenRewrite Feb 17, 2026
@timtebeek timtebeek deleted the retain-jaxb-api-for-jackson branch February 17, 2026 15:45
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.

AddJaxbDependencies removes javax.xml.bind:jaxb-api when it is required by another dependency

2 participants