Hi! TL;DR: On Java 10.0.1, a web app in Tomcat 9.0.8.0 has no access to JAXB even though its reference implementation is present on the class path.
(This looks like a bug to me, but "Before you report a bug" urged me to ask here first. :) ) NOTE: I already asked [on StackOverflow](https://stackoverflow.com/q/51518781/2525313), where the question is a little more readable. On to the details... # The Situation We have a web app that runs on Tomcat and depends on JAXB. During our migration to Java 9 we opted for adding [the JAXB reference implementation as a regular dependency](https://stackoverflow.com/a/48204154/2525313). Everything worked when launching the app from the IDE [with embedded Tomcat](https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/startup/Tomcat.html), but when running it on a real Tomcat instance, I get this error: Caused by: java.lang.RuntimeException: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath. - with linked exception: [java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory] at [... our-code ...] 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:278) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ContextFinder.find(ContextFinder.java:421) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.0.jar:2.3.0] at [... our-code ...] Caused by: java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582) ~[?:?] at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190) ~[?:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:499) ~[?:?] at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:276) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ContextFinder.find(ContextFinder.java:421) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.0.jar:2.3.0] at [... our-code ...] Note: > Implementation of JAXB-API has not been found on module path or classpath. These are the relevant files in `webapps/$app/WEB-INF/lib`: jaxb-api-2.3.0.jar jaxb-core-2.3.0.jar jaxb-impl-2.3.0.jar What is going on here? # What I tried ## Adding JARs Maybe it helps to add the JARs to Tomcat's class path in `setenv.sh`? CLASSPATH= .../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar: .../webapps/$app/WEB-INF/lib/jaxb-impl-2.3.0.jar: .../webapps/$app/WEB-INF/lib/jaxb-core-2.3.0.jar: .../webapps/$app/WEB-INF/lib/javax.activation-1.2.0.jar Nope: Caused by: javax.xml.bind.JAXBException: ClassCastException: attempting to cast jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bind/JAXBContext.class to jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bind/JAXBContext.class. Please make sure that you are specifying the proper ClassLoader. at javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.java:157) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:300) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:286) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.ContextFinder.find(ContextFinder.java:409) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721) ~[jaxb-api-2.3.0.jar:2.3.0] at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662) ~[jaxb-api-2.3.0.jar:2.3.0] at de.disy.gis.webmapserver.factory.DefaultWmsRequestFactory.initializeCommandExtractor(DefaultWmsRequestFactory.java:103) ~[cadenza-gis-webmapserver-7.7-SNAPSHOT.jar:7.6] at de.disy.gis.webmapserver.factory.DefaultWmsRequestFactory.lambda$new$0(DefaultWmsRequestFactory.java:87) ~[cadenza-gis-webmapserver-7.7-SNAPSHOT.jar:7.6] That's clearly the same class, so apparently it has been loaded by two class loaders. I suspect [the system class loader and the app's class loader](https://tomcat.apache.org/tomcat-9.0-doc/class-loader-howto.html#Class_Loader_Definitions), but why would loading `JAXBContext` be delegated to the system class loader once but not always? It almost looks as if the delegation behavior of the app's class loader changes while the program runs. ## Adding the module I don't really want to add _java.xml.bind_, but I tried it anyways by adding this to `catalina.sh`: JDK_JAVA_OPTIONS="$JDK_JAVA_OPTIONS --add-modules=java.xml.bind" Doesn't work either, though: Caused by: java.lang.ClassCastException: java.xml.bind/com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl cannot be cast to com.sun.xml.bind.v2.runtime.JAXBContextImpl at [... our-code ...] Apart from the different class and stack trace, this is in line with what happened earlier: The class `JAXBContextImpl` was loaded twice, once from _java.xml.bind_ (must have been the system class loader) and one other time (I assume by the app's loader from the JAR). ## Searching for bugs [Searching Tomcat's bug database](https://bz.apache.org/bugzilla/query.cgi) I found [#62559](https://bz.apache.org/bugzilla/show_bug.cgi?id=62559). Could that be the same error? -- PGP Key: http://keys.gnupg.net/pks/lookup?op=vindex&search=0xCA3BAD2E9CCCD509 Web: http://blog.codefx.org a blog about software development https://courses.codefx.org high-quality Java courses Social: https://twitter.com/nipafx http://youtube.com/c/codefx --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org