jboss-modules: ClassNotFoundException during static initialization of __XMLEventFactory
jameskojo Feb 11, 2014 2:00 PMApologies if this is the wrong forum for jboss-modules specific questions. I couldn't find a dedicated forum for it.
We are using jboss-modules as an embedded library in several of our applications, and deploying it in a Tomcat container as a webapp. A transitive dependency pulls in the woodstox parser (wstx-asl-3.2.9.jar), which eventually gets registered as a XmlEventFactory service provider by the container.
The woodstox parser is loaded in the webapp classloader along side the jboss-modules jars. However, the static initialization code in __XMLEventFactory seems to assume that all service providers of XmlEventFactory are in the system classloader as it swaps in the system CL for the TCCL, so of course the lookup fails.
A call to XmlEventFactory.newInstance() before the classloader swapping works just fine in my app, which suggests that the swapping is unnecessary at least in some situations, which is also implied by the code comment.
Could this behavior be made configurable or optional or otherwise enhanced?
See below for detailed context.
Thanks
James
Code in question::
static {
Thread thread = Thread.currentThread();
ClassLoader old = thread.getContextClassLoader();
// Unfortunately we can not use null because of a stupid bug in the jdk JAXP factory finder.
// Lack of tccl causes the provider file discovery to fallback to the jaxp loader (bootclasspath)
// which is correct. However, after parsing it, it then disables the fallback for the loading of the class.
// Thus, the class can not be found.
//
// Work around the problem by using the System CL, although in the future we may want to just "inherit"
// the environment's TCCL
thread.setContextClassLoader(ClassLoader.getSystemClassLoader());
try {
if (System.getProperty(XMLEventFactory.class.getName(), "").equals(__XMLEventFactory.class.getName())) {
System.clearProperty(XMLEventFactory.class.getName());
}
XMLEventFactory factory = XMLEventFactory.newInstance();
try {
DEFAULT_FACTORY = PLATFORM_FACTORY = factory.getClass().getConstructor();
} catch (NoSuchMethodException e) {
throw __RedirectedUtils.wrapped(new NoSuchMethodError(e.getMessage()), e);
}
System.setProperty(XMLEventFactory.class.getName(), __XMLEventFactory.class.getName());
} finally {
thread.setContextClassLoader(old);
}
}
Initialization Error:
Caused by: javax.xml.stream.FactoryFinder$ConfigurationError: Provider com.ctc.wstx.stax.WstxEventFactory not found
at javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:188)
at javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:148)
at javax.xml.stream.FactoryFinder.find(FactoryFinder.java:242)
at javax.xml.stream.FactoryFinder.find(FactoryFinder.java:213)
at javax.xml.stream.XMLEventFactory.newInstance(XMLEventFactory.java:59)
at __redirected.__XMLEventFactory.<clinit>(__XMLEventFactory.java:76)
at __redirected.__JAXPRedirected.initAll(__JAXPRedirected.java:80)
at org.jboss.modules.Module$1.run(Module.java:131)
at org.jboss.modules.Module$1.run(Module.java:118)
at java.security.AccessController.doPrivileged(Native Method)
at org.jboss.modules.Module.<clinit>(Module.java:118)
at org.jboss.modules.ModuleLoader.loadModuleLocal(ModuleLoader.java:355)
at org.jboss.modules.ModuleLoader.preloadModule(ModuleLoader.java:305)
at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:238)