Two artifacts declare the same module name "jakarta.activation" – this does not work.
soc opened this issue · 12 comments
Both activation and activation-api declare their module name as jakarta.activation
:
- jakarta: https://github.com/eclipse-ee4j/jaf/blob/master/activation/src/main/java/module-info.java#L11
- jakarta-api: https://github.com/eclipse-ee4j/jaf/blob/master/activationapi/pom.xml#L37
This does not work, and results in various silent (having a Maven project on Jenkins fails silently, because Jenkins does not detect the misdisagnosed "JVM crash" as a build failure) and not so silent (IntelliJ, GitLab CI) ways.
The problem has been verified on 1.x (via Automatic-Module-Name
s in MANIFEST.MF), but likely also exists on 2.x (via module-info.java).
To clarify "this does not work": The JVM fails to start if with both jakarta and jakarta-api on the module path and errors out with an java.lang.module.FindException
.
You should never have both jakarta and jakarta-api on the module path.
jakarta-api is intended only to compile against, in cases where the runtime will
supply the classes later.
jakarta is the complete runtime package, containing both API and implementation.
If you need to include the runtime with your application, this is the artifact you
should include.
(See also my comment in the PR.)
I'm not purposely including both, various third-party dependencies have the API jar or runtime jar as transitive dependencies.
I don't think it's a workable approach to let the ability to start the JVM depend on luck and the random constellation of dependencies that aren't within the control of the user.
Excluding the API dependency only works up to a certain degree, because Maven does not support POM-level exclusions – one needs to add the exclusion manually to each affected dependency, which is extremely unreliable.
I'm not purposely including both, various third-party dependencies have the API jar or runtime jar as transitive dependencies.
They're broken. File a bug against them and get them fixed.
I don't think it's a workable approach to let the ability to start the JVM depend on luck and the random constellation of dependencies that aren't within the control of the user.
No, but it depends on the user doing the right thing. You can't expect to be able to
do any set of wrong things and still have it work.
Excluding the API dependency only works up to a certain degree, because Maven does not support POM-level exclusions – one needs to add the exclusion manually to each affected dependency, which is extremely unreliable.
So get the artifacts fixed.
I know this is utterly pointless ... but which of the roughly 350 direct dependents on activation-api do you believe are broken? All of them?
Looking at this transitively means that probably 90% of the Java ecosystem is "doing it wrong"?
Is this Oracle's official position?
I know this is utterly pointless ... but which of the roughly 350 direct dependents on activation-api do you believe are broken? All of them?
I have no idea, I haven't looked at any of them. Which one did you have problems
with when you reported this issue?
Looking at this transitively means that probably 90% of the Java ecosystem is "doing it wrong"?
I doubt it.
Is this Oracle's official position?
Oracle has no official position on this. This is my position as maintainer of this code.
For instance org.glassfish:jaxb-runtime
depends on jakarta.activation:jakarta.activation-api
, jakarta.xml.bind:jakarta.xml.bind-api
does, com.fasterxml.jackson.module:jackson-module-jaxb-annotations
, ... (but the specific cases really don't matter).
Did I understand you correctly:
If I have an application that I want to run¹ – I have to go through the complete dependency graph and exclude each dependency on activation-api
by hand?
So for instance I'm forced to exclude jakarta.activation-api
in jakarta.xml.bind-api
in a project's parent pom dependencyManagement
section:
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.2</version>
++ <exclusions>
++ <exclusion>
++ <groupId>jakarta.activation</groupId>
++ <artifactId>jakarta.activation-api</artifactId>
++ </exclusion>
++ </exclusions>
</dependency>
... and then add the dependency on the implementation at every place jakarta.xml.bind-api
is actually used:
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
++ <dependency>
++ <groupId>com.sun.activation</groupId>
++ <artifactId>jakarta.activation</artifactId>
++ </dependency>
... and then repeat this for every library in every pom that depends directly or transitively on jakarta.activation-api
?
(¹ In contrast to a library, where I can just kick the can down the road and let the whole thing be an issue of the application that uses the library – which in fact seems to be the approach adopted by the library ecosystem.)
Yes, you have to work around the bugs in other libraries.
Yes, you have to work around the bugs in other libraries.
If it's a "bug" to depend on activation-api
, then why not simply drop the artefact and tell everyone to use activation
instead?
Why would any library author want to depend on activation-api
if the result is that anyone using their library can't start their application (without patching their build system)?
I'm really having a hard time getting this through to you and I'm about to stop.
I'm sorry I can't explain it well enough for you to understand it.
If it's a "bug" to depend on
activation-api
, then why not simply drop the artefact and tell everyone to useactivation
instead?
It's not a bug to depend on activation-api. But since activation-api is only intended
for compiling against, only other artifacts with the same limitation should depend on it.
Why would any library author want to depend on
activation-api
if the result is that anyone using their library can't start their application (without patching their build system)?
Because they have an artifact that defines the APIs for their library but is only used
for compiling against. If there's another part of their library that's used at runtime,
it should depend on the activation artifact.
If that's still not clear to you, I don't know how to explain it any better. Sorry.
@soc Have you found a resolution for this issue? I haven't had any crashes, but I do have warnings about jakarta.activation as an ambiguous module reference. And I’m barely getting started with a fairly small project.
I see from a search than Mr Shannon died of cancer less that three months after this colloquy, which perhaps explains why he didn't follow up on the issue. As far as I am concerned, if your design is not compatible with 3rd-part developers all over the world using requires transitive
, which may be useful for their own purposes, the problem is not with the developers. It is with the design.
I see from a search than Mr Shannon died of cancer less that three months after this colloquy, which perhaps explains why he didn't follow up on the issue.
Oh man, that's terrible to hear. :-(
Have you found a resolution for this issue?
No, there is no fix. The way the artifacts are modularized is simply not in line with the expectations of the module system.
What I was wondering is why this project diverges from similar projects in the EE space (and elsewhere), whose "impl" packages do not ship with the API themselves, but simply depend on the respective "api" packages.
If we can lift the mystery why it is done differently here, we might understand if adopting that model would work instead of JAF's current design in which the "impl" artifact duplicates the contents of the "api" artifact.