Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rule that prevents all dependencies to javax... and early jakarta.... modules to be upgraded to a Jakarta version with the new package #6

tbroyer opened this issue Apr 10, 2022 · 5 comments
a:enhancement New feature or request


Copy link

tbroyer commented Apr 10, 2022

If a project has conflicting dependencies on, say, javax.xml.bind:jaxb-api:2.3.1 and jakarta.xml.bind:jakarta.xml.bind-api:3.0.0, the plugin should let the conflicting capabilities fail the build. It currently selects the jakarta.xml.bind:jakarta.xml.bind-api:3.0.0 which is completely incompatible with javax.xml.bind:jaxb-api:2.3.1 (one uses the jakarta package, the other the javax one).

Ideally, if a project has dependencies on jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 and javax.xml.bind:jaxb-api:2.3.1, it should select jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 as both dependencies have compatible APIs (both use the javax package)

If it's at all possible, jakarta.xml.bind:jakarta.xml.bind-api:3.0.0 and jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 should also be declared incompatible (jakarta vs javax)

Copy link

As discussed in the Gradle slack:

The consumers (the libs) should say which version they need so that conflicts can be detected. [...]

api("com.sun.mail:jakarta.mail:1.6.7") { version { reject("[2.0.0,)") } }
api("com.sun.xml.bind:jaxb-impl:2.3.6") { version { reject("[3.0.0,)") } }

I think we could write a generic rule, which knows about all “Jakarta” components and their versioning scheme. This rule can then “fix” all Jakarta/Javax dependencies.

I adjusted the title of this issue.

@jjohannes jjohannes changed the title Plugin shouldn't upgrade JavaEE or JakartaEE 8 dependencies to JakartaEE 9+ ones Add rule that prevents all dependencies to javax... and early jakarta.... modules to be upgraded to a Jakarta version with the new package Apr 19, 2022
@jjohannes jjohannes added the a:enhancement New feature or request label Oct 27, 2022
@jjohannes jjohannes added this to the 1.0 milestone Oct 27, 2022
Copy link

Should probably do the following:

  • Make sure that by Add rules for more Jakarta components #7 all knowledge about javax/jakarta components is encoded in the plugin. This includes the knowledge which Jakarta component versions have jakarta and which have javax packages inside (!)
  • Then the behavior can be as follows
    1. If a thing with javax vs jakarta package is on the path, we should fail instead of resolving autoamtically (this is the original issue description)
    2. Make it configurable that javax vs jakarta is allowed (don't make them have the same capability). Because there are potential legacy situations where both can be used in parallel. This could be a special configuration option on the extension that is added for Make conflict resolution and rules configurable #1.

jjohannes added a commit that referenced this issue Nov 8, 2022
The rules now know which Jakarta version made the package
change from 'javax' to 'jakarta'. Only the versions that
have the same package as the corresponding Javax components
are now in conflict.

The rules setup follows the pattern for all rules. There is one
rule per capability. So there are now sometimes two rules to detect
conflicts between APIs and different implementations of a certain
Javax/Jakarta component:
- Javax...Rule (for javax capability)
- Jakarta...Rule (for jakrata capability)

Related to #6
Copy link

I did some work here (released in 0.7).

The change is that now all Javax*Rules know which ist the first "Jakrata Version". Only versions below that, which still contain the javax package, now get the corresponding javax capability. With that it is, for instance, possible to use javax.inject and jakarta.inject in parallel. Note that in order to achieve that, you need to use the corresponding javax component (e.g. javax.inject:javax.inject:1 and jakarta.inject:jakarta.inject-api:2.0.1) because you can never have two versions of the same component (e.g. jakarta.inject:jakarta.inject-api:1.0.5 and jakarta.inject:jakarta.inject-api:2.0.1 cannot be used together because they have the same coordinates).

A consequence of this is that sometimes there are now two rules, and with that two capabilities, you might need to consider or choose from. This is to cover other aspects like the conflict between and API and an implementation (e.g. jakrata.mail:jakarta.mail-api vs com.sun.mail:jakarta.mail). So for example there is:

All rule implementations now strictly follow the pattern that there is one Rule Class per capability. And that class has a list of MODULES to which the corresponding capability is added. (And then there might be special handling, like just adding the capability to certain versions of some of the MODULES.)

Regarding the original issue description
I tried some things to forbid an upgrade from a lower *jakarta version (with javax package) to a higher version. One thing I thought could work is removing the *jakarta capability (which the components implicitly have) from the versions that contain the javax package. This only works partially. Because the version conflict resolution is done before capabilities are even considered (during the traversal of the graph) a certain *jakarta component can still be upgraded even if the lower version would have the capability removed.

Putting it differently: The idea that one component (with one GA coordinate) is always the same (just different version of the same thing) is hard-coded in the whole concept of how dependency resolution is done in Gradle (and in Maven as well). What was done here when the Jakarta components were released with this versioning, was just wrong from the Dependency Resolution perspective in the Grdle/Maven world and it cannot be fixed that easily with capabilities.

There are other things one could consider, like rejecting versions as I wrote further up. Or one could maybe think of a clever way to replace the artifacts (the Jars) themselves or rewrite them with transforms. In my mind, this is beyond the scope of this plugin right now. Each solution would need to be generic enough to apply to (almost) all Java projects and that might be very hard to do. So if done, it would probably be good to do it in a separate plugin that folks can decide to use in addition to his one (or not).

I'll keep this issue open for further discussion on that if someone is interested. I don't think I'll do anything more here for now, but I am happy to help if someone wants to work on something in this direction.

@jjohannes jjohannes removed this from the 1.0 milestone Nov 18, 2022
Copy link

I experimented with dealing with these Jakarta EE 8 artifacts (I can't imagine what folks were thinking, it'd have been much better if they'd waited for EE 9). I came to the conclusion it'd take variants attributes to cause them to conflict, which have really unfriendly error messages on conflict, so I punted on solving that, and just make sure we have a javax grouped artifact on the classpath.

For JAXB specifically, I documented an option that allows both to exist here:

I've also since published a plugin to help with projects making the leap to Jakarta EE 9, without it being a huge source migration:

Copy link

britter commented May 24, 2024

Given there has not been any activity here, we don't intend to do anything for the moment.

@britter britter closed this as completed May 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
a:enhancement New feature or request
None yet

No branches or pull requests

4 participants