I have encountered the following problem while trying to use maven shade plugin with the code that uses JAXB.
I would like to pack my code into uber-jar with all dependencies shaded, so I include the following into pom.xml:
<relocations>
<relocation>
<pattern>com</pattern>
<shadedPattern>quase.com</shadedPattern>
</relocation>
<!-- ... other top-level patterns for external dependencies -->
<relocation>
<pattern>org</pattern>
<shadedPattern>quase.org</shadedPattern>
<excludes>
<exclude>org.aau.**</exclude> <!-- my own code is not shaded -->
</excludes>
</relocation>
</relocations>
The problem is that my code uses JAXB (default rt.jar implementation), so after calling the initialization:
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://ift.tt/Qb9Hvl", false);
JAXBContext jaxbContext = JAXBContext.newInstance(ADOXML.class);
ADOXML adoxml = (ADOXML) jaxbContext.createUnmarshaller().unmarshal(
new SAXSource(spf.newSAXParser().getXMLReader(),
new InputSource(String.valueOf(new File(fileName).toURI()))));
I got the following error:
[java.lang.ClassNotFoundException: quase.com.sun.xml.internal.bind.v2.ContextFactory]
at quase.javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:241)
at quase.javax.xml.bind.ContextFinder.find(ContextFinder.java:455)
at quase.javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:652)
at quase.javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:599)
at quase.org.aau.quase.quontology.builder.QuBuilderUtils.getModelFromFile(QuBuilderUtils.java:185)
at quase.org.aau.quase.quontology.ontology.QuOntologyOWLAPI.createOntologyFromModel(QuOntologyOWLAPI.java:574)
at org.aau.quase.quontology.builder.QuSiteOntologyBuilder.main(QuSiteOntologyBuilder.java:43)
Caused by: java.lang.ClassNotFoundException: quase.com.sun.xml.internal.bind.v2.ContextFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at quase.javax.xml.bind.ContextFinder.safeLoadClass(ContextFinder.java:573)
at quase.javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:239)
... 6 more
It seems that the rt.jar implementation of JAXB (which includes com.sun.xml.internal.bind.v2.ContextFactory
) is not getting shaded with the rest of the dependencies because it is not available to me separately - only as a part of rt.jar so it is not included into uber-jar. But the code which calls it got modified and expects the shaded version i.e. quase.com.sun.xml.internal.bind.v2.ContextFactory
.
I tried to do two things to resolve this issue:
-
I have tried to explicitly un-shade the offending class:
<relocation> <pattern>com</pattern> <shadedPattern>quase.com</shadedPattern> <excludes> <exclude>com.sun.xml.internal.bind.v2.**</exclude> </excludes> </relocation>
but this seemed to have little effect, as now I got an error in this form
[java.lang.ClassNotFoundException: quase/com.sun.xml.internal.bind.v2.ContextFactory] at quase.javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:241) ...
so now instead of missing the class in a shaded package i.e.
quase.com.sun...
it misses the class in a kind of directory i.e.quase/com.sun...
This seems to be a problem with the reflection handling in the shade plugin, as the reflection-based calls got modified to expect shaded versions regardless of excluding the classes being called from shading. -
I have tried to grab the complete control over JAXB version I am using by putting the non-rt.jar versions of JAXB (jaxb-api-2.2.11.jar and jaxb-impl-2.2.11.jar) into "endorsed" directory and making maven know about it:
<compilerArguments> <endorseddirs>c:/java/jdk1.8.0_31/lib/endorsed</endorseddirs> </compilerArguments>
but this still has no effect for some reason - the error is the same as above so the code still expects the rt.jar version of the JAXB code to be called (as non-rt versions of JAXB do not include
com.sun.xml.internal.bind
but insteadcom.sun.xml.bind
).
What am I doing wrong? Any suggestions?
Aucun commentaire:
Enregistrer un commentaire