I have two Java modules, A and B. A provides a core model with JAXB annotations and helper classes for creating doing JAXB stuff (creating the context, marshalling, unmarshalling, etc.) B provides additional classes that are included in the model via @XmlAnyElement(lax = true) and must therefore be added to the JAXB context.
This works fine in plain Java - B's classloader sees all the relevant classes and can instantiate the JAXB context with:
JAXBContext.newInstance(RootFromA.class, RootFromB.class)
Now I'm trying the same with OSGI (B is an Eclipse plug-in and A is the core library that will also be used by a plain Java command line module C). After much trial and error, I've managed to get A and B to see both the JAXB API and implementation via OSGI package imports. The problem is that calling newInstance as above seems to use the JAXB API's classloader, not the one of RootFromA, and certainly not the one of RootFromB. As such, it fails to even see the JAXB implementation and complains that it can't find the ContextFactory class.
I've managed to resolve this by calling a different version of newInstance:
JAXBContext.newInstance(
RootFromA.class.getPackageName()
+ ":" + RootFromB.class.getPackageName(),
RootFromB.class.getClassLoader())
I don't like this, for two reasons:
- My "client" code (B being the client of the JAXB helper stuff in A) has to manually provide a fitting classloader.
- I have to provide jaxb.index files in all referenced packages that list the context classes, even though my code is perfectly aware of them and actually gets the package name from the classes.
There probably isn't any way around (1), because only B knows the full set of classes and can decide whose classloader is able to see all of them. I'm worried though that I might run into more trouble once I add extension modules C and D that hook into B via Eclipse extension points and provide additional classes for the JAXB context - will B's classloader be able to see those?
But I'd really find a way to get rid of the static index files required for (2). The full set of context classes is dynamic and decided in plain Java by a ServiceLoader and in Eclipse by an extension point. In both cases I have direct access to the full set of classes that should belong to the context, and thus consider having to manually add jaxb.index files to each package redundant and therefore a potential and unnecessary source of error.
Am I missing something? Is there a "nicer" way to do this? And why isn't there a newInstance method that takes a set of context classes and a classloader?