ops4j / org.ops4j.pax.transx

Transaction Manager and JMS / JDBC pooling support
Apache License 2.0
9 stars 7 forks source link

Use javax.transaction 1.2 dependencies only, while keeping [1.1,2) Import range #33

Closed grgrzybek closed 3 years ago

grgrzybek commented 3 years ago

There are many Maven artifacts providing javax.transaction package, most importantly:

Of course in multiple versions. Jakarta libraries provide either javax.transaction or jakarta.transaction packages.

IMO we need only one such dependency. At runtime, it can be e.g., Karaf that provides relevant packages.

grgrzybek commented 3 years ago

We still should assume that JDK8 is the most used JDK, but we have to be aware of what's happening in the recommended JDK (11 and soon, 17).

(See Add module java.transaction to export API javax.transaction for details)

JDK 8 has two packages in rt.jar:

JDK 11 has only one javax.transaction.xa package in javax.transaction.xa.jmod and the module is defined like this:

module java.transaction.xa {
    exports javax.transaction.xa;
}

jakarta.transaction-api-1.3.3-sources.jar and javax.transaction-api-1.3-sources.jar differ only by comment headers.

javax.transaction-api-1.2.jar contains (as expected) javax.transaction.xa. The exception classes in this version miss serialVersionUID.

Bundles for JTA 1.3 import javax.transaction.xa package without exporting them:

Export-Package: \
  javax.transaction;\
    uses:="javax.interceptor,javax.transaction.xa,javax.enterprise.util,javax.enterprise.context";\
    version="1.3.3"

Import-Package: \
  javax.enterprise.context,\
  javax.enterprise.util,\
  javax.interceptor;version="[1.2,1.2.98)",\
  javax.transaction;version="1.3.3",\
  javax.transaction.xa

Bundle for JTA 1.2 has:

Export-Package: \
  javax.transaction;\
    uses:="javax.enterprise.context,javax.enterprise.util,javax.transaction.xa,javax.interceptor";\
    version="1.2",
  javax.transaction.xa;\
    version="1.2"

Import-Package: \
  javax.enterprise.context,\
  javax.enterprise.util,\
  javax.interceptor;version="[1.2,1.2.98)",\
  javax.transaction;version="1.2",\
  javax.transaction.xa;version="1.2"

So the desired (IMO) state is:

grgrzybek commented 3 years ago

This situation is complicated because of DBCP2...

DBCP-445 and DBCP-454 introduced https://github.com/apache/commons-dbcp/commit/7363c4040d4d0bfc89761c904f4332c69420099c where the import declaration is:

javax.transaction.xa;version="1.1.0";partial=true;mandatory:=partial

Karaf, with KARAF-6715 tackled DBCP2 resolution problem by adding proper version 1.1 to javax.transaction/javax.transaction.xa packages already exported with partial=true; mandatory:=partial...

But I just realized that it's wrong or at least very confusing (both on DBCP2 and Karaf side)...

grgrzybek commented 3 years ago

My tests show few confusing scenarios...

After the above analysis, I see that everything works thanks to ... Require-Bundle: system.bundle of javax.transaction-api bundle.

grgrzybek commented 3 years ago

It's not so good with jakarta.transaction-api bundle. It can't be resolved on clean Karaf, as it imports javax.transaction.xa package (same as javax.transaction-api bundle), but without Require-Bundle: system.bundle, so it can't pass through the weird partial=true; mandatory:=partial markings on exported javax.transaction.xa package in Karaf's jre.properties.

grgrzybek commented 3 years ago

See: https://github.com/javaee/javax.transaction/commit/cafce67773652a48d37f4f18cd317cfbd6371802#diff-5b28dfac4685527f0aa99f6fde21966a5347c363d64baf1680fd1db0b0f14e73

grgrzybek commented 3 years ago

For completeness:

grgrzybek commented 3 years ago

@gnodet hello (cc: @jbonofre @ffang), I'd like to refer to https://github.com/apache/karaf/commit/d69f71a8fe550357b9d6addfe951c3fe1e1d7eee which you may not remember (2009!). I understand how the partial attribute works. It is shown in 3.13.1 "Require-Bundle" chapter of OSGi core (partial is just arbitrary name, the point is it is mandatory).

I'm just (see my above comments) trying to justify why Karaf still uses this attribute in javax.transaction and javax.transaction.xa exports from system bundle (etc/jre.properties). What I found is:

So definitely my attempt to fix DBCP2 usage in Karaf (see: https://issues.apache.org/jira/browse/KARAF-6715), simply by adding version="1.1" is only a partial fix of general JTA usage in Karaf.

Karaf's transaction-api feature, with non-dependency:

mvn:javax.transaction/javax.transaction-api/1.2

is a good thing, but works only by accident, because this particular API bundle has:

Require-Bundle: system.bundle

Which ensures that javax.transaction.xa.XAResource is always loaded from JDK itself:

If mvn:javax.transaction/javax.transaction-api/1.2 didn't have (see https://github.com/javaee/javax.transaction/commit/cafce67773652a48d37f4f18cd317cfbd6371802#diff-5b28dfac4685527f0aa99f6fde21966a5347c363d64baf1680fd1db0b0f14e73) Require-Bundle: system.bundle, DBCP2 would use different javax.transaction.xa.XAResource than bundles importing this interface from javax.transaction-api leading to CCE. and if Karaf wouldn't boot delegate javax.transaction.xa, DBCP2 would not be resolved, because it'd have been exposed to javax.transaction.xa package through 2 different chains - from system bundle that can have partial attribute and through javax.transaction-api.

I created https://issues.apache.org/jira/browse/DBCP-571 to check how we could resolve this issue once and for all.

grgrzybek commented 3 years ago

Another interesting facts.

https://github.com/eclipse-ee4j/jta-api/commit/79d477b6b1503099af62c2b25fcb854f4b17a7e3 confirmed that api and spec submodules of jakarta.transaction-api can be versioned separately, which ensures me that while the specification version is 1.3, API version of the javax.transaction package should stay at 1.2

https://github.com/eclipse-ee4j/jta-api/commit/9256156ed6ec5d3bf3bdd5c66ca0071f78b381b1 moved the code to api submodule, but top-level osgi.bundle file was not touched. So api/pom.xml, while still having:

<_include>-${basedir}/osgi.bundle</_include>

doesn't actually use this file, so Require-Bundle: system.bundle trick that made javax.transaction-api work, doesn't work with jakarta.transaction-api. See original trick here: https://github.com/javaee/javax.transaction/commit/cafce67773652a48d37f4f18cd317cfbd6371802#diff-5b28dfac4685527f0aa99f6fde21966a5347c363d64baf1680fd1db0b0f14e73

grgrzybek commented 3 years ago

I've created two PRs:

grgrzybek commented 3 years ago

All tests pass. The changes are: