Issue
I'm getting major headaches trying to get Eclipse, Java 11, OSGI, and JAXB to cooperate.
My project consists of several modules:
- A plain Java core library (let's call it The Core) that provides most of the functionality
- A plain Java command line tool that uses the Core
- An Eclipse Plug-in (for use in the IDE) (let's call this The Plug-in) that also uses the Core
The core has several points where functionality can be extended. On the plain Java side, this is automated through service loaders, but there are also hooks to manually register extensions. The Plug-in defines extension points and call those registration hooks with their data.
Here comes the problem: The Core has code to serialise and deserialise a model tree between my Java model and XML via JAXB. Some parts of the model come from extensions - when creating the JAXB context, I list my model root class and all extension classes as my context classes.
This works fine on the Java side, but causes problems on the Eclipse side, as I'll describe below.
I'm using Maven to build the whole project. Not because I like Maven (I don't), but because Eclipse's build documentation is horribly thin and I was at least roughly aware of methods to build Plug-ins with Maven. I've not been able to figure out how to create an Eclipse Plug-in project that directly includes my plain Java Core (without having to manually copy each updated Core build into the Plug-in), but after much fiddling with the Apache Felix Maven plugin, I've managed to get the following system of modules usable:
- Core module (Packaging type: jar)
- Command line module (Packaging type: jar, creates an executable jar; irrelevant for this discussion)
- OSGI module (Packaging type: bundle)
- Eclipse Plug-in (not a Maven module, but a plain Eclipse Plug-in project that has the OSGI module as a dependency)
This allows me to work on the core, run my Maven build with tests (which updates the OSGI project) and then simply do a Refresh/Maven update in Eclipse to get everything updated in the Plug-in project.
Now this works fine, including JAXB serialisation, as long as I don't have to access JAXB in the Plug-in myself (i.e. just calling my API methods in Core). Because of the extension mechanism, the Plug-in will now add extension classes to the model that need JAXB annotations. And not only that, they will (I assume) have to use the same JAXB API lib as the Core library (included in the Plug-in via the OSGI wrapper). Assumption: I have to export the JAXB API packages in the OSGI wrapper, so that client projects (i.e. the Plug-in) can use them, without having to bring their own (supposedly conflicting) JAXB dependencies.
And even that part works. Almost. Or sort of. I've actually managed to get it "running" by manually adding "javax.xml.bin.annotation" to the exported packages listed for the Felix plugin in my POM, and it produces an OSGI manifest that contains a matching "Export-Package" entry. And the Plug-in now compiles with JAXB annotations, and the Core handles the Plug-in's JAXB-annotated classes correctly.
But Eclipse complains about the OSGI manifest:
Package 'javax.xml.bind.annotation' does not exist in this plug-in
That not only means that I have to click away a warning dialogue every time I start the Plug-in (because Eclipse believes one of its dependencies is broken), but also a) that I expect major troubles with deployment once I've finished development and b) that I have an uncanny feeling that I'm going about this the wrong way.
Which after this long (but necessary, I guess) description comes down to these questions:
- Why is Eclipse complaining about the OSGI manifest if it actually works in the actual Eclipse Plug-in? Is there a way I can fix the manifest?
- Is it a correct approach to have the OSGI/Eclipse side of things get the JAXB dependencies from the plain Java Core?
- If not, how can I get JAXB dependencies into the Plug-in the OSGI way? (I haven't found any info on how and where to get correct, up to date OSGI dependencies for either the standard implementation (java.xml.bind for the API and com.sun.xml.bind for the implementation if I've got that right) or Moxy) How can I make sure that my plain Java Core code, which handles the JAXB context and knows nothing about OSGI & Co, understands the annotations on the OSGI side if that brings its own separate JAXB depedencies?
- (Bonus question) Is my OSGI wrapper project really necessary? Is there no way to have a Maven setup that builds a few plain Java modules and as its last item an Eclipse plug-in that directly depends on the earlier modules, along with their dependencies?
Solution
- The system library of Java 11 does not contain
javax.xml.bind.annotation
anymore. Which means that the now missing package must be contained and exported by a plugin/bundle instead. Plugins/bundles usingjavax.xml.bind.annotation
must have either a correspondingImport-Package
(recommended) orRequire-Bundle
(not recommended) entry now. - No, since it needs to be an OSGi bundle. Maven itself cannot resolve OSGi dependencies because, for instance
Import-Package
statements are based on package level versioning, but in a Maven repository there are only versions on module/JAR level. - When you want to use the same JAR in a plain Java application and in an OSGi application like Eclipse, you have to specify the dependencies twice, in the
pom.xml
and in theMETA-INF/MANIFEST.MF
. To be sure, that both dependencies definitions are correct, you also have to build the JAR twice, e.g. with plain Maven and with Maven+Tycho. The build for the plain Java application will get the dependencies from e.g. a Maven repository and the build for the Eclipse plugin will get the dependencies from the target platform from p2 repositories (in your case e.g.javax.xml.bind
from Eclipse Orbit). - No. See 3.
Answered By - howlger
Answer Checked By - Candace Johnson (JavaFixing Volunteer)