Schlagwort-Archive: tycho

Java 11, JAXB and osgi

Starting with Java 11, several packages have been “hard-removed” from the JRE itself (For Java 9 and 10 they were simply re-activateable by using a parameter) – one of those being the javax.xml.bind package, which used to provide (together with others) the JAXB implementation.

Updating our product to become Java 11 compatible, proved to be a major task, but finally it seems I managed to do it. So here are the effective steps resp. pitfalls that one will run into:

  • The JAXB packages are not available anymore – how to find them?
  • My bundles have to run on both Java 8 and Java >8 – how to achieve this?
  • Tycho is reluctant to build this, i miss packages
  • The concrete JAXB implementation seems not to be found, because OSGi – how to fix this?

The missing JAXB packages

In order to find replacements for the now missing bundles, we have to find the right set applicable for OSGi. I managed to identify the following maven bundles:

com.sun.activation:javax.activation:1.2.0
javax.xml.bind:jaxb-api:2.4.0-b180830.0359
com.sun.xml.bind:jaxb-osgi:2.4.0-b180830.04

You can use a maven tool like p2-maven-plugin to create a p2 repository with these requirements for later inclusion. Have a look at our own dependency repo for an example.

Run ’em on both Java 8 and Java >8

OSGi R7 introduced the support for multi-release jars. These are bundles, where, dependent on the java version you use, different manifest information is to be applied.

The following picture shows an example where for Java >=9 the Import-Package of the original manifest is replaced to import com.sun.xml.bind.v2. The resp. Import-Package will not be used for Java <=8. In order to activate this, the main manifest has to be extended with Multi-Release: true

The MANIFEST.MF in versions/9/OSGI-INF extends the original manifest for Java > 8

Tycho: com.sun.source where are you?

Caveat Building with Java 11 does not yet work – all builds are done using Java 8

While com.sun.xml.bind.jaxb-osgi 2.4.0.b180830_0438 works fine within the IDE, when building your product trouble is on the horizon.

com.sun.xml.bind.jaxb-osgi 2.4.0.b180830_0438 formally requires the packages com.sun.source.tree and com.sun.source.util which are not provided to OSGi as they are expected to be made available by the JRE. At runtime, org.eclipse.osgi_3.13.100.v20180827-1536 cares for this but at build and package time it is not satisfied.

This can be fixed by providing a special fragment with Fragment-Host: system.bundle; extension:=framework which may then be included to your feature.

See https://github.com/eclipse-ee4j/jaxb-api/issues/92 for the detailed problem description and http://blog.meschberger.ch/2008/10/osgi-bundles-require-classes-from.html for infos on its solution.

My own solution to this problem is shown in the following image:

Providing com.sun.source.tree and com.sun.source.util to the OSGi environment

Implementation of JAXB-API has not been found

At runtime javax.xml.bind.ContextFinder.newInstance is used to create a JAXB object that is actually performing the work. ContextFinder is part of the java-api bundle, and the actual JAXB implementation it tries to find is provided by com.sun.xml.bind.jaxb-osgi.

Now in OSGi we face the problem of the classloaders per bundle being separate. In https://github.com/eclipse-ee4j/jaxb-api/issues/78 the problem of jaxb-api not able to find the real jaxb api implementation is documented.

The exception that identifies this problem looks like this

[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]


Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:269) ~[na:na]
… 93 common frames omitted

Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[na:na]
… 97 common frames omitted

As far as I know, there are currently 2 solutions to this problem:

1. Add Import-Package for com.sun.xml.bind.v2 for each bundle and adapt JAXBContext.newInstance to use a bundle local classloader

2. Provide a fragment bundle for java-api that adds the dependency to the jaxb-api implementation package.

After trying the first approach, I though that I have to modify to much of the existing code – hence I moved to the second approach.

The first image in this blog post actually shows this fragment.