highsource / highsource/jaxb-tools
Since 4.0.13, jaxb-maven-plugin no longer resolves the common ancestor type for a choice group whose member types come from a dependency module (regresses to List)
- Dominant language
- Java
- Stars
- 465
- Forks
- 105
- PR merge metrics
- No merged PRs in 30d
Description
## Summary
When a `` group's member elements are typed with complex types that share a common
ancestor via `xs:extension`, and those types are defined in a *different Maven module* that the
current module depends on via a plain `` (not listed under the jaxb-maven-plugin's
own ``), XJC/`-Xinheritance` correctly infers the common ancestor as the
collection element type up through 4.0.12. Starting with 4.0.13 it silently falls back to
`List`.
Bisected to PR #668 ("move to maven-resolver-api", fixing #663), released in 4.0.13.
## Root cause (as far as I can tell)
- Pre-4.0.13, `resolveXJCPluginArtifacts()` built an `ArtifactResolutionRequest` with
`setArtifact(project.getArtifact())` and `setResolveRoot(false)`. That combination, via the
legacy Maven `RepositorySystem`, resolved not only the declared `` dependencies but
also (as an apparent side effect) the current module's own `` graph, putting
their compiled classes on the XJC plugin classloader.
- Post-4.0.13 (`ArtifactResolverUtils.resolveTransitively`), the Aether `CollectRequest` uses a
bare-coordinate root artifact (no dependency info) and only `collectRequest.setDependencies(...)`
from the `` list - the module's own `` are never folded in.
- If a module's XSD choice group references types whose common ancestor class is only reachable
through a project `` (typical when that ancestor is defined and JAXB-compiled in a
separate schema module, exposed to this module only via an `` reference), that
ancestor class is no longer visible on the XJC classpath, and the common-base-type computation
(whichever plugin/code performs it under `-Xinheritance`) can't resolve it, silently degrading
to `Object`.
I want to stress "silently" - this doesn't fail the build, it just changes generated code, which
then breaks callers that assigned the getter's return value to a `List` variable
(as would compile against 4.0.12-generated sources).
## Minimal reproduction
Attached: `jaxb-repro.zip` — two throwaway Maven modules.
- `module-a`: XSD defines `Shape` (base complexType) and `Circle`/`Square` (extend `Shape`).
Generated + registers an episode.
- `module-b`: depends on `module-a` as a plain `` (not under ``), imports
`module-a`'s namespace via the episode, and defines:
```xml
```
Toggle the `jaxb-plugins.version` property in the parent `pom.xml` and rebuild:
```
mvn clean install -Djaxb-plugins.version=4.0.12 # -> public List getCircleOrSquare()
mvn clean install -Djaxb-plugins.version=4.0.13 # -> public List getCircleOrSquare()
```
Verified on both `mvn` and `mvnd`, JDK 21.
## Workaround
Explicitly redeclare the ancestor-providing module under the jaxb-maven-plugin's own
`` list (with `combine.children="append"` if you don't want to repeat the
whole default list), so its classes stay on the XJC classloader regardless of resolver internals:
```xml
org.example.jaxbrepro
module-a
${project.version}
```
This works but has to be applied per affected module, and is easy to miss since the failure mode
is silent (no build error, just a behavior change in generated code).
## Ask
Would it make sense for `resolveXJCPluginArtifacts()` to also fold in the current project's own
compile-scope dependencies (optionally behind a flag, since I understand the 4.0.13 change may
have been intentional scope-narrowing rather than purely a side-effect of the API migration)?
Happy to open a PR if a maintainer can confirm the desired behavior.
Contributor guide
Research direction
Start in resolveXJCPluginArtifacts() and ArtifactResolverUtils.resolveTransitively, comparing the pre-4.0.13 and post-4.0.13 dependency-resolution paths. Rebuild the attached two-module reproduction from its parent pom.xml with plugin versions 4.0.12 and 4.0.13, then add a regression test covering the generated getter type. Done means the intended dependency scope is confirmed and the silent List regression is addressed or explicitly documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100