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:
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
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:
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
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.