You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Nicolai Parlog <ni...@codefx.org> on 2018/07/26 10:41:13 UTC

JAXB not available on Tomcat 9 and Java 10

 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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: JAXB not available on Tomcat 9 and Java 10

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Nicolaj,

On 8/8/18 1:17 AM, Nicolai Parlog wrote:
> Hi,
> 
> with the help of an answer on StackOverflow we have solved this.
> In case anybody was watching this, here's what happened...
> 
> First some random facts:
> 
> * if not given a class loader 
> (https://javaee.github.io/jaxb-v2/doc/user-guide/ch06.html#d0e6919),
>
> 
`JAXBContext::newInstance` will use [the thread's context class
> loader 
> (https://docs.oracle.com/javase/10/docs/api/java/lang/Thread.html#getC
ontextClassLoader())
>
> 
when looking for the JAXB implementation - this is the case even if
> you call `newInstance(Class...)` (one might mistakenly think it
> uses the provided class instances' loader) * Tomcat builds a small
> class loader hierarchy 
> (https://tomcat.apache.org/tomcat-9.0-doc/class-loader-howto.html) 
> to separate web applications from one another * by not relying on
> the module _java.xml.bind_, in Java 9, JAXB classes are not loaded
> by the bootstrap or system class loader
> 
> So here's what happened on Java 8:
> 
> * we don't pass a class loader to JAXB (oops), so it uses the 
> thread's context class loader * our conjecture is that Tomcat does
> not explicitly set the context class loader and so it will end up
> being the same one that loaded Tomcat: the system class loader

This is almost certainly an incorrect assumption. While an application
is processing a request, the TCCL should be that of the webapp's
ClassLoader. Any other situation would be a security problem.

> * that's dandy because the system class loader sees the entire JDK 
> and hence the JAXB implementation included therein
> 
> Java 9 enters - the piano stops playing and everybody puts down
> their scotch:
> 
> * we added JAXB as a regular dependency 
> (https://stackoverflow.com/a/48204154/2525313) and so it is loaded
> by the web app's class loader * just as on Java 8, JAXB searches
> the system class loader, though, and that one can't see the app's
> loader (only the other way around)

If your above assumption were true, then this would be true. But I
believe both of these assumptions are false.

It's easy to test your hypothesis: just print the value of the TCCL at
the point where you think JAXB is using the wrong one. If it's a
WebappClassLoader, then your analysis above is incorrect.

If it's printing the (somewhat confusingly called the) "application"
ClassLoader or "system" classloader, or "null", then something running
in your environment has broken the TCCL, and it's probably no Tomcat's
fault.

> * JAXB fails to find the implementation and goes belly up
> 
> The solution is to make sure JAXB uses the right class loader. We
> know of three ways:
> 
> * call
> 
> `Thread.getCurrentThread().setContextClassLoader(this.getClass().getCl
assLoader());`
>
> 
but that's not really a good idea
> * create a context resolver
> 
> (https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ContextResolver.
html),
>
> 
but that requires JAX-WS and that feels like replacing one evil with
> another * use the package-accepting variant of
> `JAXBContext::newInstance` that also takes a class loader and pass
> the correct loader, although that requires some refactoring

JAXB using the TCCL is entirely appropriate. You need to find out why
the TCCL is wrong.

Try running your application under a SecurityManager and you'll find
out where the TCCL is being set pretty quickly :)

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - https://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAltsezMACgkQHPApP6U8
pFh76BAAlFiN/qNZm5LSXRAriskFn3HMl6+dNdxzQt8xhVJAIvZt9yE+ntA6RMYd
vcXGCR/Ttb/f1wKGxKK6sfgifGWJXuL6+XRL6n0DaKicAN9euGY8qZh2wxarp0Aa
wa38zY1PemREkPpJZWphwT1jl/XCXzg/d7k+DCmcOMnKoAtGeH/J/AU18ay5dk97
FfDtVSSbMcp1R0QYNkC9rVta7A1cSgzVVnGHzu6sia7KViiG1/3f5yJEM3NlI9pe
EYKzo0N2h901TMDpv81NhGs0qeTkQQZHojtQsg7GWs29DQMXNeBP/Wv/ciuriuHA
B0E+NtS3MJRY2LZ3XTBPx3BvSY5giUGolt7tU6LDtKEMuiDMFkCrtdi5Useo1BTt
OJZxaphzuqPG94DhsO5b4/t9hNuZ1YurKZDcQ7j2UkI9/TwPiW33ch7T6qzIn6ZO
vKi/AAZQsYuOyGEOb7UZj8N2PFMXLXkbv+WX+QtvbnEM/0+s4AHejvxlcLE6I3k3
gUoHwqV+MXccZeEfgKgZm5xURES4AynBXR4BGMbUk6VZOryAVP80G3GKnkebNaK/
RrR0f4WbHDRKOp0azRFDWqmjkKwb4dYJTUWX8hhw1M4oTxRoiJx0pvcjK49sgkaH
Fx8MXxhCp00mWY4sOysXtNrHc+Tw8qvonFpO0juLc65/ttSafpI=
=GGUk
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: JAXB not available on Tomcat 9 and Java 10

Posted by Nicolai Parlog <ni...@codefx.org>.
 Hi,

with the help of an answer on StackOverflow we have solved this. In
case anybody was watching this, here's what happened...

First some random facts:

* if not given a class loader
  (https://javaee.github.io/jaxb-v2/doc/user-guide/ch06.html#d0e6919),
  `JAXBContext::newInstance` will use [the thread's context class
  loader
(https://docs.oracle.com/javase/10/docs/api/java/lang/Thread.html#getContextClassLoader())
  when looking for the JAXB implementation - this is the case even if
  you call `newInstance(Class...)` (one might mistakenly think it uses
  the provided class instances' loader)
* Tomcat builds a small class loader hierarchy
  (https://tomcat.apache.org/tomcat-9.0-doc/class-loader-howto.html)
  to separate web applications from one another
* by not relying on the module _java.xml.bind_, in Java 9, JAXB
  classes are not loaded by the bootstrap or system class loader

So here's what happened on Java 8:

* we don't pass a class loader to JAXB (oops), so it uses the
  thread's context class loader
* our conjecture is that Tomcat does not explicitly set the context
  class loader and so it will end up being the same one that loaded
  Tomcat: the system class loader
* that's dandy because the system class loader sees the entire JDK
  and hence the JAXB implementation included therein

Java 9 enters - the piano stops playing and everybody puts down their
scotch:

* we added JAXB as a regular dependency
  (https://stackoverflow.com/a/48204154/2525313) and so it is
  loaded by the web app's class loader
* just as on Java 8, JAXB searches the system class loader, though,
  and that one can't see the app's loader (only the other way around)
* JAXB fails to find the implementation and goes belly up

The solution is to make sure JAXB uses the right class loader. We know
of three ways:

* call

`Thread.getCurrentThread().setContextClassLoader(this.getClass().getClassLoader());`
  but that's not really a good idea
* create a context resolver

(https://docs.oracle.com/javaee/7/api/javax/ws/rs/ext/ContextResolver.html),
  but that requires JAX-WS and that feels like replacing one evil with
  another
* use the package-accepting variant of `JAXBContext::newInstance` that
  also takes a class loader and pass the correct loader, although that
  requires some refactoring

 so long ... Nicolai



On 26.07.2018 12:41, Nicolai Parlog wrote:
> 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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: JAXB not available on Tomcat 9 and Java 10

Posted by Mark Thomas <ma...@apache.org>.
On 27/07/18 15:36, Nicolai Parlog wrote:
>  Hi Christopher,
> 
> unfortunately that didn't change the observable behavior - exact same
> error message as when the JARs were in the application's lib folder.

Java 10.0.2
Tomcat 9.0.11-dev

I added the following to WEB-INF/lib:
activation-1.1.1.jar
jaxb-api-2.3.0.jar
jaxb-core-2.3.0.1.jar
jaxb-impl-2.3.0.1.jar

And then the following JSP worked:
<%
javax.xml.bind.JAXBContext.newInstance(org.apache.catalina.users.MemoryUser.class);
%>

I suggest the following:

Produce the smallest, simplest JSP that reproduces the problem with the
above libraries and then we can look at this further.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: JAXB not available on Tomcat 9 and Java 10

Posted by Nicolai Parlog <ni...@codefx.org>.
 Hi Christopher,

unfortunately that didn't change the observable behavior - exact same
error message as when the JARs were in the application's lib folder.

 so long ... Nicolai



On 26.07.2018 17:37, Christopher Schultz wrote:
> Nicolai,
> 
> On 7/26/18 6:41 AM, Nicolai Parlog wrote:
>> 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/catali
>
>> 
na/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.ja
>
>> 
va: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.j
>
>> 
ava: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/bi
>
>> 
nd/JAXBContext.class
>> to 
>> jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bi
>
>> 
nd/JAXBContext.class.
> 
> 
> Please make sure that you are specifying the proper ClassLoader.
>> at 
>> javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.ja
>
>> 
va: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.initializeCo
>
>> 
mmandExtractor(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.ht
>
>> 
ml#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?
> 
> You will likely need to include these classes in Tomcat's 
> CATALINA_BASE/lib directory; it appears that placing them into
> your application is causing some confusion.
> 
> You should not put any JAR files that are bundled into your 
> application into Tomcat's CLASSPATH. Better to simply move the
> JARs from your application's WEB-INF/lib directory to Tomcat's 
> CATALINA_BASE/lib directory and make no changes to the CLASSPATH.
> 
> -chris
> 
> ---------------------------------------------------------------------
>
> 
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 

-- 

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: JAXB not available on Tomcat 9 and Java 10

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Nicolai,

On 7/26/18 6:41 AM, Nicolai Parlog wrote:
> 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/catali
na/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.ja
va: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.j
ava: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/bi
nd/JAXBContext.class
> to 
> jar:file:.../webapps/$app/WEB-INF/lib/jaxb-api-2.3.0.jar!/javax/xml/bi
nd/JAXBContext.class.
>
> 
Please make sure that you are specifying the proper ClassLoader.
> at 
> javax.xml.bind.ContextFinder.handleClassCastException(ContextFinder.ja
va: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.initializeCo
mmandExtractor(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.ht
ml#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?

You will likely need to include these classes in Tomcat's
CATALINA_BASE/lib directory; it appears that placing them into your
application is causing some confusion.

You should not put any JAR files that are bundled into your
application into Tomcat's CLASSPATH. Better to simply move the JARs
from your application's WEB-INF/lib directory to Tomcat's
CATALINA_BASE/lib directory and make no changes to the CLASSPATH.

- -chris
-----BEGIN PGP SIGNATURE-----
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIzBAEBCAAdFiEEMmKgYcQvxMe7tcJcHPApP6U8pFgFAltZ6rAACgkQHPApP6U8
pFi6ZA/8DXK7Y4M7/VW0wxbZ5Psr5+IwlPGk1SZb/+ZlpylPNcOjsW2K+MzycK1P
VT5+fqsCD7Aj9u6OF8D0B2aN7khDJp53F0UqwLw3kymHP3/0b/oeoZWgeDkYpXpQ
QKoEwpS1N0FVjeHH11R5sdJBv7nURLAaV85VZo1TfLqqfs9RmJUxiV6c5u46gM1d
vODdOgoRwqRJxLMGNJBnGAMMYkGS6/jcX+eteopeEO/rtia6imxgU+dLLsrNoPDk
ilEK3xETrKFeT4PFkLujMBlu7/Zf+HAik53IL/u5C1h72iiEkIRv/+9kmuBprVww
pj2nEmDZkZgUylYYCb1RDK/5qWInwXaXO3dpz9IJbnNq5UDUs8pSiRb2Gi1eMNvM
7zXCz7usg73N7fJMnFdvPmugsqucTXiuLzN6JYQIi+qY8iKHLDL0n2scNJKXKluq
+ad2mKUSOBnELf2cyoDQ6lWt3iNOFNHHmB4F5bbyw19NVIndnRiej2KFZ6HkFutd
BkpMoaX0PWiRAb657DqHT+3kJTBhcA4npkUPLUi5rjyQogh3p74I+WVHO67dx/f2
6TGamIgunxY25tQTGfW4alCLwpEmW+2tdzxAJ2NHv3Yxs793vtgE3puptgrxt5Lr
Q8Enku/ugN6tFsdpaCaEqdwyJkgoC3LsT3+sbZQ1cHtvofdrtrg=
=PzJF
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org