Discussion:
NoClassDefFoundError using Xerces / XmlResolver
Jean-Baptiste MARTIN
2016-04-21 10:03:13 UTC
Permalink
Hello,

I've built a simple bundle which instanciate a
"org.apache.xerces.util.XMLCatalogResolver" object.
In my pom, I've had these dependencies and plugin :

<build>
<plugins>
<!-- Plugin to create bundle -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>myXMLResolver</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.16.1</version>
<type>bundle</type>
<scope>provided</scope>
</dependency>
<!-- xerces is provided in /lib/endorsed/ folder of ServiceMix -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>

<artifactId>org.apache.servicemix.bundles.xmlresolver</artifactId>
<version>1.2_5</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
</dependencies>
</build>


Testing the bundle "locally" (within the IDE) is working fine.
Deploying it into the /deploy folder is also fine (its status is "Active").
When running it (through Camel route), I get this stacktrace :

Caused by: java.lang.NoClassDefFoundError:
org/apache/xml/resolver/CatalogManager
at org.apache.xerces.util.XMLCatalogResolver.init(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown Source)[:]
at
myXMLResolver.MainBean.run(MainBean.java:17)[241:test.myXMLResolver:0.0.1.SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)[:1.7.0_95]
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_95]
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_95]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_95]
at
org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:408)[199:org.apache.camel.camel-core:2.16.1]
at
org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:279)[199:org.apache.camel.camel-core:2.16.1]
at
org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:252)[199:org.apache.camel.camel-core:2.16.1]
... 19 more


Ok, the class "CatalogManager" from package "org.apache.xml.resolver"
existed in compile-time but not in run-time. So I deploy
"org.apache.servicemix.bundles.xmlresolver" dependency into /deploy folder.
When executing in Karaf console the command "bundle:headers
<xmlresolver_bundle_id>", I get :
Export-Package =
...
org.apache.xml.resolver;uses:="org.apache.xml.resolver.helpers,javax.xml.parsers,org.apache.xml.resolver.readers";version=1.2,
...

Nevertheless, same stacktrace appears.

Even if I add the package "org.apache.xml.resolver" in the <Import-Package>
I get the same error...
Any idea of what's going on ?


I'm using ServiceMix 6.1.0 (w/ Karaf 3.0.5), running on Java 7.


Thanks,
Jean-Baptiste Martin
Jean-Baptiste MARTIN
2016-04-25 14:49:20 UTC
Permalink
Update (to give more information, but it doesn't solve the issue) :

Here is the bundle's MANIFEST.MF :

Manifest-Version: 1.0
Bnd-LastModified: 1461311084908
Build-Jdk: 1.7.0_95
Bundle-ManifestVersion: 2
Bundle-Name: myXMLResolver
Bundle-SymbolicName: test.myXMLResolver
Bundle-Version: 0.0.1.SNAPSHOT
Created-By: Apache Maven Bundle Plugin
Export-Package:
myXMLResolver;version="0.0.1";uses:="org.apache.camel,org.apache.xerces.util"
Import-Package:
org.apache.camel;version="[2.16,3)",org.apache.xerces.util;version="[2.11,3)"
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.7))"
Tool: Bnd-2.4.1.201501161923

If I add the package org.apache.xml.resolver in the <Import-Package>,
Import-Package from MANIFEST become :
org.apache.camel;version="[2.16,3)",org.apache.xerces.util;version="[2.11,3)",org.apache.xml.resolver;version="[1.2,2)"


Even if the org.apache.xml.resolver is precised in <Import-Package>, and
the bundle "org.apache.servicemix.bundles.xmlresolver" exports
org.apache.xml.resolver, the issue is not solved.


Workaround :

A workaround can be done :
1. Put the bundle "org.apache.servicemix.bundles.xmlresolver" in
<SMX_HOME>/lib/endorsed folder
2. In the file <SMX_HOME>/etc/config.properties, add
"org.apache.xml.resolver" for the property
"org.osgi.framework.system.package.extra".

But it doesn't look like a clean method...
Still working on it. If you have advices, don't hesitate :)


Jean-Baptiste Martin
Post by Jean-Baptiste MARTIN
Hello,
I've built a simple bundle which instanciate a
"org.apache.xerces.util.XMLCatalogResolver" object.
<build>
<plugins>
<!-- Plugin to create bundle -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>myXMLResolver</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.16.1</version>
<type>bundle</type>
<scope>provided</scope>
</dependency>
<!-- xerces is provided in /lib/endorsed/ folder of ServiceMix -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.xmlresolver</artifactId>
<version>1.2_5</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
</dependencies>
</build>
Testing the bundle "locally" (within the IDE) is working fine.
Deploying it into the /deploy folder is also fine (its status is "Active").
org/apache/xml/resolver/CatalogManager
at org.apache.xerces.util.XMLCatalogResolver.init(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown Source)[:]
at
myXMLResolver.MainBean.run(MainBean.java:17)[241:test.myXMLResolver:0.0.1.SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)[:1.7.0_95]
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_95]
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_95]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_95]
at
org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:408)[199:org.apache.camel.camel-core:2.16.1]
at
org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:279)[199:org.apache.camel.camel-core:2.16.1]
at
org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:252)[199:org.apache.camel.camel-core:2.16.1]
... 19 more
Ok, the class "CatalogManager" from package "org.apache.xml.resolver"
existed in compile-time but not in run-time. So I deploy
"org.apache.servicemix.bundles.xmlresolver" dependency into /deploy folder.
When executing in Karaf console the command "bundle:headers
Export-Package =
...
org.apache.xml.resolver;uses:="org.apache.xml.resolver.helpers,javax.xml.parsers,org.apache.xml.resolver.readers";version=1.2,
...
Nevertheless, same stacktrace appears.
Even if I add the package "org.apache.xml.resolver" in the
<Import-Package> I get the same error...
Any idea of what's going on ?
I'm using ServiceMix 6.1.0 (w/ Karaf 3.0.5), running on Java 7.
Thanks,
Jean-Baptiste Martin
Jean-Baptiste Onofré
2016-04-26 05:08:29 UTC
Permalink
Hi,

your problem is that xerces comes from different classloader.

Your bundle should not export these package: just import or private.

As the resolver uses xerces, they should go in the same classloader (so
from lib/endorsed).

Let me double check your use case.

Regards
JB
Post by Jean-Baptiste MARTIN
Hello,
I've built a simple bundle which instanciate a
"org.apache.xerces.util.XMLCatalogResolver" object.
<build>
<plugins>
<!-- Plugin to create bundle -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>myXMLResolver</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.16.1</version>
<type>bundle</type>
<scope>provided</scope>
</dependency>
<!-- xerces is provided in /lib/endorsed/ folder of ServiceMix -->
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.xmlresolver</artifactId>
<version>1.2_5</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
</dependencies>
</build>
Testing the bundle "locally" (within the IDE) is working fine.
Deploying it into the /deploy folder is also fine (its status is "Active").
org/apache/xml/resolver/CatalogManager
at org.apache.xerces.util.XMLCatalogResolver.init(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown Source)[:]
at
myXMLResolver.MainBean.run(MainBean.java:17)[241:test.myXMLResolver:0.0.1.SNAPSHOT]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)[:1.7.0_95]
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_95]
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_95]
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_95]
at
org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:408)[199:org.apache.camel.camel-core:2.16.1]
at
org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:279)[199:org.apache.camel.camel-core:2.16.1]
at
org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:252)[199:org.apache.camel.camel-core:2.16.1]
... 19 more
Ok, the class "CatalogManager" from package "org.apache.xml.resolver"
existed in compile-time but not in run-time. So I deploy
"org.apache.servicemix.bundles.xmlresolver" dependency into /deploy folder.
When executing in Karaf console the command "bundle:headers
Export-Package =
...
org.apache.xml.resolver;uses:="org.apache.xml.resolver.helpers,javax.xml.parsers,org.apache.xml.resolver.readers";version=1.2,
...
Nevertheless, same stacktrace appears.
Even if I add the package "org.apache.xml.resolver" in the <Import-Package>
I get the same error...
Any idea of what's going on ?
I'm using ServiceMix 6.1.0 (w/ Karaf 3.0.5), running on Java 7.
Thanks,
Jean-Baptiste Martin
--
Jean-Baptiste Onofré
***@apache.org
http://blog.nanthrax.net
Talend - http://www.talend.com
Jean-Baptiste MARTIN
2016-05-18 14:00:58 UTC
Permalink
Hi !

Indeed, it's a classloading problem, thanks.

I've investigated a bit more on OSGi classloading and I've a question about
the choice of putting *xercesImpl* lib in the *<SMX_HOME>/lib/endorsed*
folder.
If I understood correctly, if a lib is contained in *endorsed *folder and
its packages are exported / delegated (thanks to
*<SMX_HOME>/etc/config.properties*), then its classes will be loaded with
the Bootstrap / Primordial classloader. This is the case for *XercesImpl*.
But, since :

- Bootstrap / Primordial classloader has no parent (-> see schema below)
- Classloaders can reach classes loaded by their parents but the
opposite is not true (e.g. Extension classloader can't reach classes loaded
by System / Application classloader)
- XmlResolver has its own classloader (because it's loaded as a bundle
and its packages aren't exported/delegated)
- *XercesImpl *uses *XmlResolver*


shouldn't *XmlResolver *be also added in *endorsed* folder and has its
classes exported/delegated (as you said Jb) *by default* ? Is it the only
solution if we want to use *xmlResolver *from *Xerces* ? Then, every
bundles used by *Xerces *should be in *endorsed *?
Why having put *xercesImpl *in *endorsed *folder ? Why not set *xercesImpl *as
a bundle at the same level of *xmlResolver *? (there is a good reason but I
can't determine which one).


It's always easier to understand with a schema, so here is the OSGi
classloading hierarchy (even if I'm sure you know it ;) )

Bootstrap / Primordial classloader (classes from <JRE_HOME>/lib : rt.jar,
i18n.jar, ... and also in our case from <SMX_HOME>/lib/endorsed :
xercesImpl-2.11.0.jar, ...)
|
|
v
Extension classloader (classes from <JRE_HOME>/lib/ext/ and
<SMX_HOME>/lib/ext)
|
|
v
System / Application classloader (classes from classpath)
|
|
v
OSGi environment (URLClassloader) (classes in osgi-core.jar,
felix-framework.jar, ... and classes from <SMX_HOME>/lib)
| |
| |
v v
Bundle A classloader xmlResolver classloader
(org.apache.servicemix.bundles.xmlresolver-1.2_5.jar)


Thanks,
Jean-Baptiste Martin
Post by Jean-Baptiste Onofré
Hi,
your problem is that xerces comes from different classloader.
Your bundle should not export these package: just import or private.
As the resolver uses xerces, they should go in the same classloader (so
from lib/endorsed).
Let me double check your use case.
Regards
JB
Post by Jean-Baptiste MARTIN
Hello,
I've built a simple bundle which instanciate a
"org.apache.xerces.util.XMLCatalogResolver" object.
<build>
<plugins>
<!-- Plugin to create bundle -->
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.4</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Import-Package>*</Import-Package>
<Export-Package>myXMLResolver</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>2.16.1</version>
<type>bundle</type>
<scope>provided</scope>
</dependency>
<!-- xerces is provided in /lib/endorsed/ folder of ServiceMix
-->
Post by Jean-Baptiste MARTIN
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.xmlresolver</artifactId>
<version>1.2_5</version>
<type>bundle</type>
<scope>compile</scope>
</dependency>
</dependencies>
</build>
Testing the bundle "locally" (within the IDE) is working fine.
Deploying it into the /deploy folder is also fine (its status is
"Active").
Post by Jean-Baptiste MARTIN
org/apache/xml/resolver/CatalogManager
at org.apache.xerces.util.XMLCatalogResolver.init(Unknown Source)[:]
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown
Source)[:]
Post by Jean-Baptiste MARTIN
at org.apache.xerces.util.XMLCatalogResolver.<init>(Unknown
Source)[:]
Post by Jean-Baptiste MARTIN
at
myXMLResolver.MainBean.run(MainBean.java:17)[241:test.myXMLResolver:0.0.1.SNAPSHOT]
Post by Jean-Baptiste MARTIN
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native
Method)[:1.7.0_95]
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)[:1.7.0_95]
Post by Jean-Baptiste MARTIN
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)[:1.7.0_95]
Post by Jean-Baptiste MARTIN
at java.lang.reflect.Method.invoke(Method.java:606)[:1.7.0_95]
at
org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:408)[199:org.apache.camel.camel-core:2.16.1]
Post by Jean-Baptiste MARTIN
at
org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:279)[199:org.apache.camel.camel-core:2.16.1]
Post by Jean-Baptiste MARTIN
at
org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:252)[199:org.apache.camel.camel-core:2.16.1]
Post by Jean-Baptiste MARTIN
... 19 more
Ok, the class "CatalogManager" from package "org.apache.xml.resolver"
existed in compile-time but not in run-time. So I deploy
"org.apache.servicemix.bundles.xmlresolver" dependency into /deploy
folder.
Post by Jean-Baptiste MARTIN
When executing in Karaf console the command "bundle:headers
Export-Package =
...
org.apache.xml.resolver;uses:="org.apache.xml.resolver.helpers,javax.xml.parsers,org.apache.xml.resolver.readers";version=1.2,
Post by Jean-Baptiste MARTIN
...
Nevertheless, same stacktrace appears.
Even if I add the package "org.apache.xml.resolver" in the
<Import-Package>
Post by Jean-Baptiste MARTIN
I get the same error...
Any idea of what's going on ?
I'm using ServiceMix 6.1.0 (w/ Karaf 3.0.5), running on Java 7.
Thanks,
Jean-Baptiste Martin
--
Jean-Baptiste Onofré
http://blog.nanthrax.net
Talend - http://www.talend.com
Loading...