Re: JAXB not available on Tomcat 9 and Java 10

2018-08-09 Thread Christopher Schultz
-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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: JAXB not available on Tomcat 9 and Java 10

2018-08-07 Thread Nicolai Parlog
 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

Re: JAXB not available on Tomcat 9 and Java 10

2018-08-01 Thread Mark Thomas
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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: JAXB not available on Tomcat 9 and Java 10

2018-07-27 Thread Nicolai Parlog
 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

Re: JAXB not available on Tomcat 9 and Java 10

2018-07-26 Thread Christopher Schultz
-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

JAXB not available on Tomcat 9 and Java 10

2018-07-26 Thread Nicolai Parlog
 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 load