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

Conflict while loading javax.transaction.xa.XAResource on JDK 17 #5630

Open
reda-alaoui opened this issue Dec 31, 2024 · 11 comments
Open

Conflict while loading javax.transaction.xa.XAResource on JDK 17 #5630

reda-alaoui opened this issue Dec 31, 2024 · 11 comments

Comments

@reda-alaoui
Copy link

reda-alaoui commented Dec 31, 2024

Describe the bug
With a particular set of OSGI modules, the DataService stops working. Same issue as #4141 . With the same error:

Caused by: java.lang.LinkageError: loader constraint violation in interface itable initialization for class org.h2.jdbcx.JdbcXAConnection: when selecting method 'javax.transaction.xa.XAResource javax.sql.XAConnection.getXAResource()' the class loader 'platform' for super interface javax.sql.XAConnection, and the class loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @5c45582b of the selected method's class, org.h2.jdbcx.JdbcXAConnection have different Class objects for the type javax.transaction.xa.XAResource used in the signature (javax.sql.XAConnection is in module java.sql of loader 'platform'; org.h2.jdbcx.JdbcXAConnection is in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @5c45582b, parent loader 'platform')

To Reproduce

Not clear enough.

Expected behavior

I shouldn't have a class loader conflict on javax.transaction.xa.XAResource.

Screenshots

Screenshot from 2024-12-30 18-17-52

Target Environment (please complete the following information):

  • Docker
  • OS version: Official docker image

Additional context

It looks like javax.transaction.xa.XAResource is first loaded from the platform class loader from java system module java.transaction.xa, then from file:/opt/eclipse/kura/plugins/org.apache.geronimo.specs.geronimo-jta_1.1_spec_1.1.1.jar:

2024-12-31T08:26:09.868215524Z [8.252s][info][class,load] java.lang.ClassLoader$$Lambda$652/0x000076b09f511550 source: java.lang.ClassLoader
2024-12-31T08:26:09.868320934Z [8.252s][info][class,load] javax.transaction.xa.XAResource source: file:/opt/eclipse/kura/plugins/org.apache.geronimo.specs.geronimo-jta_1.1_spec_1.1.1.jar
2024-12-31T08:26:09.868386430Z [8.252s][info][class,load] org.h2.jdbcx.JdbcXAConnection source: file:/opt/eclipse/kura/plugins/com.h2database_2.1.214.jar
2024-12-31T08:26:09.868494694Z [8.252s][info][class,load] javax.transaction.xa.XAException source: file:/opt/eclipse/kura/plugins/org.apache.geronimo.specs.geronimo-jta_1.1_spec_1.1.1.jar

Currently, the official distribution adds --add-modules=ALL-SYSTEM to the Kura java launch command line. Maybe it should exclude module java.transaction.xa.

@reda-alaoui
Copy link
Author

Or maybe org.apache.geronimo.specs.geronimo-jta_1.1_spec_1.1.1.jar should be removed ?

@reda-alaoui
Copy link
Author

Or maybe org.apache.geronimo.specs.geronimo-jta_1.1_spec_1.1.1.jar should be removed ?

Tested, this option doesn't work because other modules pull geronimo directly.

@reda-alaoui
Copy link
Author

FTR, the issue happens when adding the following OSGI modules:

  • SFL4J 2.0.16
  • Apache Aries
  • Logback classic

@gnunzi
Copy link
Contributor

gnunzi commented Jan 3, 2025

Hi Réda,

which other modules "pull directly geronimo"?

To me it looks you have a conflict with the h2db plugin, which is indeed a core module of Kura. The dataservice uses the h2db for buffering.

Apache Aries seems to be a bulky framework, from the website I see it ships JTA: this sounds like the source of your problem, since javax.transaction is apparently shipped by the h2db module already.

Also Geronimo claims to provide JavaEE libraries. Is this Geronimo part of the official Kura docker Image or part of Aries?

As a side note: no need to install logging modules like sfl4j or logback. Just use those shipped in Kura already.

Hope it helps.

@gnunzi
Copy link
Contributor

gnunzi commented Jan 3, 2025

Hi @reda-alaoui again,
after reading #4141, your suggestion sounds very valuable to me:

Currently, the official distribution adds --add-modules=ALL-SYSTEM to the Kura java launch command line. Maybe it should exclude module java.transaction.xa.

In #4141 it is clear that both the platform loader AND the EquinoxClassLoader loaded the same class javax.transaction.xa.XAResource. It would then make sense to exclude java.transaction.xa from the jvm directive.

I am not sure though the issue in #4141 is the same as yours.

BR,

@reda-alaoui
Copy link
Author

reda-alaoui commented Jan 4, 2025

Hello @gnunzi ,

As a side note: no need to install logging modules like sfl4j or logback. Just use those shipped in Kura already.

If I am not mistaken, Kura provides SLF4J version 1.x. I have dependencies requiring SLF4J 2.x.

Apache Aries seems to be a bulky framework, from the website I see it ships JTA: this sounds like the source of your problem, since javax.transaction is apparently shipped by the h2db module already.

I tried to use Aries to satisfy SLF4J 2.x requirement regarding osgi.serviceloader.processor by following https://stackoverflow.com/a/77867804/3761154 .

Is this Geronimo part of the official Kura docker Image or part of Aries?

Part of official Kura docker Image (via Eclipse Equinox?).

after reading #4141, your suggestion sounds very valuable to me:

FTR I tried to exclude java.transaction.xa and java.sql from the modules loaded by the JDK. It didn't fix the issue.
I think this had no effect because the JDK 17 used by Kura official Docker image has something special.
A "classic" JDK 17 should have a jmod directory listing the system modules. For example on Ubuntu, the Temurin distribution jmod directory looks like this:

rhousni@rhousni:~/.jdks/temurin-17.0.13/jmods$ ll
total 78084
drwxrwxr-x 2 rhousni rhousni     4096 oct.  18 18:27 ./
drwxrwxr-x 9 rhousni rhousni     4096 oct.  18 18:27 ../
-rw-r--r-- 1 rhousni rhousni 22230315 oct.  18 18:27 java.base.jmod
-rw-r--r-- 1 rhousni rhousni   130563 oct.  18 18:27 java.compiler.jmod
-rw-r--r-- 1 rhousni rhousni    59129 oct.  18 18:27 java.datatransfer.jmod
-rw-r--r-- 1 rhousni rhousni 13708649 oct.  18 18:27 java.desktop.jmod
-rw-r--r-- 1 rhousni rhousni    46559 oct.  18 18:27 java.instrument.jmod
-rw-r--r-- 1 rhousni rhousni   128135 oct.  18 18:27 java.logging.jmod
-rw-r--r-- 1 rhousni rhousni   903072 oct.  18 18:27 java.management.jmod
-rw-r--r-- 1 rhousni rhousni    99801 oct.  18 18:27 java.management.rmi.jmod
-rw-r--r-- 1 rhousni rhousni   475363 oct.  18 18:27 java.naming.jmod
-rw-r--r-- 1 rhousni rhousni   757207 oct.  18 18:27 java.net.http.jmod
-rw-r--r-- 1 rhousni rhousni    69382 oct.  18 18:27 java.prefs.jmod
-rw-r--r-- 1 rhousni rhousni   272038 oct.  18 18:27 java.rmi.jmod
-rw-r--r-- 1 rhousni rhousni    48084 oct.  18 18:27 java.scripting.jmod
-rw-r--r-- 1 rhousni rhousni   618205 oct.  18 18:27 java.security.jgss.jmod
-rw-r--r-- 1 rhousni rhousni    89346 oct.  18 18:27 java.security.sasl.jmod
-rw-r--r-- 1 rhousni rhousni     9857 oct.  18 18:27 java.se.jmod
-rw-r--r-- 1 rhousni rhousni    63294 oct.  18 18:27 java.smartcardio.jmod
-rw-r--r-- 1 rhousni rhousni    83674 oct.  18 18:27 java.sql.jmod
-rw-r--r-- 1 rhousni rhousni   221218 oct.  18 18:27 java.sql.rowset.jmod
-rw-r--r-- 1 rhousni rhousni    11687 oct.  18 18:27 java.transaction.xa.jmod
-rw-r--r-- 1 rhousni rhousni   693560 oct.  18 18:27 java.xml.crypto.jmod
-rw-r--r-- 1 rhousni rhousni  5220392 oct.  18 18:27 java.xml.jmod
-rw-r--r-- 1 rhousni rhousni    58045 oct.  18 18:27 jdk.accessibility.jmod
-rw-r--r-- 1 rhousni rhousni    38236 oct.  18 18:27 jdk.attach.jmod
-rw-r--r-- 1 rhousni rhousni  1197716 oct.  18 18:27 jdk.charsets.jmod
-rw-r--r-- 1 rhousni rhousni  9247287 oct.  18 18:27 jdk.compiler.jmod
-rw-r--r-- 1 rhousni rhousni   386646 oct.  18 18:27 jdk.crypto.cryptoki.jmod
-rw-r--r-- 1 rhousni rhousni   139722 oct.  18 18:27 jdk.crypto.ec.jmod
-rw-r--r-- 1 rhousni rhousni   165924 oct.  18 18:27 jdk.dynalink.jmod
-rw-r--r-- 1 rhousni rhousni    15298 oct.  18 18:27 jdk.editpad.jmod
-rw-r--r-- 1 rhousni rhousni  2335141 oct.  18 18:27 jdk.hotspot.agent.jmod
-rw-r--r-- 1 rhousni rhousni   114753 oct.  18 18:27 jdk.httpserver.jmod
-rw-r--r-- 1 rhousni rhousni   325192 oct.  18 18:27 jdk.incubator.foreign.jmod
-rw-r--r-- 1 rhousni rhousni  1070788 oct.  18 18:27 jdk.incubator.vector.jmod
-rw-r--r-- 1 rhousni rhousni    15168 oct.  18 18:27 jdk.internal.ed.jmod
-rw-r--r-- 1 rhousni rhousni   102419 oct.  18 18:27 jdk.internal.jvmstat.jmod
-rw-r--r-- 1 rhousni rhousni   437535 oct.  18 18:27 jdk.internal.le.jmod
-rw-r--r-- 1 rhousni rhousni    90608 oct.  18 18:27 jdk.internal.opt.jmod
-rw-r--r-- 1 rhousni rhousni   454063 oct.  18 18:27 jdk.internal.vm.ci.jmod
-rw-r--r-- 1 rhousni rhousni     9647 oct.  18 18:27 jdk.internal.vm.compiler.jmod
-rw-r--r-- 1 rhousni rhousni     9654 oct.  18 18:27 jdk.internal.vm.compiler.management.jmod
-rw-r--r-- 1 rhousni rhousni   267389 oct.  18 18:27 jdk.jartool.jmod
-rw-r--r-- 1 rhousni rhousni  1385104 oct.  18 18:27 jdk.javadoc.jmod
-rw-r--r-- 1 rhousni rhousni   139086 oct.  18 18:27 jdk.jcmd.jmod
-rw-r--r-- 1 rhousni rhousni   477667 oct.  18 18:27 jdk.jconsole.jmod
-rw-r--r-- 1 rhousni rhousni   746249 oct.  18 18:27 jdk.jdeps.jmod
-rw-r--r-- 1 rhousni rhousni   850184 oct.  18 18:27 jdk.jdi.jmod
-rw-r--r-- 1 rhousni rhousni   151291 oct.  18 18:27 jdk.jdwp.agent.jmod
-rw-r--r-- 1 rhousni rhousni   648455 oct.  18 18:27 jdk.jfr.jmod
-rw-r--r-- 1 rhousni rhousni   423412 oct.  18 18:27 jdk.jlink.jmod
-rw-r--r-- 1 rhousni rhousni   743246 oct.  18 18:27 jdk.jpackage.jmod
-rw-r--r-- 1 rhousni rhousni   686368 oct.  18 18:27 jdk.jshell.jmod
-rw-r--r-- 1 rhousni rhousni    10752 oct.  18 18:27 jdk.jsobject.jmod
-rw-r--r-- 1 rhousni rhousni    37542 oct.  18 18:27 jdk.jstatd.jmod
-rw-r--r-- 1 rhousni rhousni 10252729 oct.  18 18:27 jdk.localedata.jmod
-rw-r--r-- 1 rhousni rhousni    97373 oct.  18 18:27 jdk.management.agent.jmod
-rw-r--r-- 1 rhousni rhousni    62226 oct.  18 18:27 jdk.management.jfr.jmod
-rw-r--r-- 1 rhousni rhousni    77780 oct.  18 18:27 jdk.management.jmod
-rw-r--r-- 1 rhousni rhousni    69855 oct.  18 18:27 jdk.naming.dns.jmod
-rw-r--r-- 1 rhousni rhousni    30860 oct.  18 18:27 jdk.naming.rmi.jmod
-rw-r--r-- 1 rhousni rhousni    31412 oct.  18 18:27 jdk.net.jmod
-rw-r--r-- 1 rhousni rhousni    10223 oct.  18 18:27 jdk.nio.mapmode.jmod
-rw-r--r-- 1 rhousni rhousni    29530 oct.  18 18:27 jdk.random.jmod
-rw-r--r-- 1 rhousni rhousni    93572 oct.  18 18:27 jdk.sctp.jmod
-rw-r--r-- 1 rhousni rhousni    75028 oct.  18 18:27 jdk.security.auth.jmod
-rw-r--r-- 1 rhousni rhousni    32852 oct.  18 18:27 jdk.security.jgss.jmod
-rw-r--r-- 1 rhousni rhousni    21629 oct.  18 18:27 jdk.unsupported.desktop.jmod
-rw-r--r-- 1 rhousni rhousni    24980 oct.  18 18:27 jdk.unsupported.jmod
-rw-r--r-- 1 rhousni rhousni    49990 oct.  18 18:27 jdk.xml.dom.jmod
-rw-r--r-- 1 rhousni rhousni   112796 oct.  18 18:27 jdk.zipfs.jmod

The JDK 17 used by Kura official Docker image does not have this directory.

@gnunzi
Copy link
Contributor

gnunzi commented Jan 4, 2025

If you need SLF4J 2.x., then the best approach would be to add SLF4J 2.x. only.
I did not test it, but you could try with https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j/2.0.16 and https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j/2.0.16. Do the bundles get activated?

Do you own the code with the SLF4J 2.x dependency? If so, you could alternatively embedd the SLF4J 2.x jar inside your bundle (change the pom file).

FTR I tried to exclude java.transaction.xa and java.sql from the modules loaded by the JDK. It didn't fix the issue.

Yes, but it probably can fix the issue in #4141 😃 There the issue appears after a hot deployment of a plugin. In your case, the issues seems to appear at boot - please correct if wrong. Imo the root cause is different.

IMO The entire Aries is not needed and is probably creating the conflict. Just add the SLF4J 2.x. dependency - best as a standalone OSGi bundle or alternatively as embedded jar in your own bundle like said above.

Makes sense?

@reda-alaoui
Copy link
Author

reda-alaoui commented Jan 4, 2025

If you need SLF4J 2.x., then the best approach would be to add SLF4J 2.x. only.

That's what I tried before getting an error regarding capability osgi.serviceloader.processor which is required by SLF4J 2.x.

I did not test it, but you could try with https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j/2.0.16 and https://mvnrepository.com/artifact/org.slf4j/log4j-over-slf4j/2.0.16. Do the bundles get activated?

From https://www.slf4j.org/legacy.html :

SLF4J ships with a module called log4j-over-slf4j. It allows log4j 1.x users (but not log4j 2.x) to migrate existing applications/libraries to SLF4J without changing a single line of code but simply by replacing the log4j.jar file with log4j-over-slf4j.jar, [...].

My module doesn't use log4j, so it seems it doesn't fit my use case.

If so, you could alternatively embedd the SLF4J 2.x jar inside your bundle (change the pom file).

That's the workaround I used before opening this ticket. But not ideal because I then have to embed SLF4J + Logback in each module requiring them.

In your case, the issues seems to appear at boot - please correct if wrong.

Maybe it appears after the boot of Aries which happens at platform boot. Didn't try to deploy Aries after the platform boot.

IMO The entire Aries is not needed and is probably creating the conflict

Again Aries was a way to provide osgi.serviceloader.processor to SLF4J 2.x 🤷‍♂️ 🥹

@reda-alaoui
Copy link
Author

reda-alaoui commented Jan 4, 2025

I realize I didn't mention it explicitly, but for information, I have exactly the same error as #4141 with SLF4J + Aries + Logback:

Caused by: java.lang.LinkageError: loader constraint violation in interface itable initialization for class org.h2.jdbcx.JdbcXAConnection: when selecting method 'javax.transaction.xa.XAResource javax.sql.XAConnection.getXAResource()' the class loader 'platform' for super interface javax.sql.XAConnection, and the class loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @5c45582b of the selected method's class, org.h2.jdbcx.JdbcXAConnection have different Class objects for the type javax.transaction.xa.XAResource used in the signature (javax.sql.XAConnection is in module java.sql of loader 'platform'; org.h2.jdbcx.JdbcXAConnection is in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @5c45582b, parent loader 'platform')

@gnunzi
Copy link
Contributor

gnunzi commented Jan 5, 2025

Thanks for all the infos 😃
I follow-up on the dependency resolution of SLF4J 2.x.

My module doesn't use log4j, so it seems it doesn't fit my use case.

Of course you can add the LogBack bundle instead of Log4J. However your LogBack bundle might clash with the Log4J bundle shipped with Kura in the future.

That's what I tried before getting an error regarding capability osgi.serviceloader.processor which is required by SLF4J 2.x.

Apparently version 2.0.0 did not have this requirement. You can try using v.2.0.0 of SLF4J.

Still if you need osgi.serviceloader.processor, wouldn't just the following bundle solve the problem instead of Aries: https://mvnrepository.com/artifact/org.osgi/org.osgi.service.serviceloader/1.0.0 ?

That's the workaround I used before opening this ticket. But not ideal because I then have to embed SLF4J + Logback in each module requiring them.

Nope 😃 You embed those two jars in one bundle and that one bundle exports the packages. Check Kura modules with embedded+exported jars as example.

Maybe you can try https://mvnrepository.com/artifact/org.slf4j/slf4j-api/2.0.0 . This won´t fix the problem with javax.transaction.xa.XAResource, but hopefully avoid it.

@gnunzi
Copy link
Contributor

gnunzi commented Jan 5, 2025

A follow-up on javax.transaction.xa.XAResource. IMO the bundle's EquinoxClassLoader should not load that class, but apparently does it.

This thread explains the following:

equinox knows about spec'ed packages from the JRE for a given JSE level. These spec'ed packages are automatically exported by the Equinox system.bundle depending on the execution environment level you are at (e.g. J2SE-1.3, J2SE-1.4 etc.)

So as long as you define a "org.osgi.framework.executionenvironment", equinox should load the right JVM packages and export them for consumption by the bundles.

So you could add the following to Kura's config.ini:

org.osgi.framework.executionenvironment=JavaSE-9 (JavaSE-1.8 or JavaSE-9 are defined in equinox)

Alternatively to the executionenvironment (best approach), you could specify the following only:

org.osgi.framework.bootdelegation=javax.transaction.*

See https://github.com/eclipse-equinox/equinox/blob/59d4c5b758e08c8fd892525f1b2991289bb6f0d8/bundles/org.eclipse.osgi/JavaSE-9.profile#L245 and https://github.com/eclipse-equinox/equinox/blob/59d4c5b758e08c8fd892525f1b2991289bb6f0d8/bundles/org.eclipse.osgi/JavaSE-9.profile#L165

So far my understanding. I hope it works. Maybe someone else can join the discussion.
BR,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants