[jetty-user] Classloader conflicts ?
Paul Bennett <[email protected]> Tue, 17 May 2011 09:52:08 -0400
| Newsgroups | gmane.comp.java.jetty.support |
|---|---|
| Message-ID | <[email protected]> |
I'm trying to embed Jetty in a Groovy app, but seemingly getting messed up by class loader conflicts. Given this:
class TestServlet extends HttpServlet {
public void init() {
try {
super.init();
} catch (ServletException e) {
e.printStackTrace();
}
ObjectStore store = ObjectStore.getInstance();
println "Servlet gets store ID=${store}, class=${System.identityHashCode(store.class)}, loader=${store.class.classLoader}"
}
}
class EmbeddedWebServer {
Server server
void start() {
if(!server) {
try {
server = new Server(5001);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.setClassLoader(Thread.currentThread().getContextClassLoader());
server.setHandler(context);
println ("Thread class loader=${Thread.currentThread().getContextClassLoader()}");
Servlet servlet = new TestServlet()
println "ApplicationServlet gets ID=${servlet}, class=${System.identityHashCode(servlet.class)}, loader=${servlet.class.classLoader}"
println "Servlet class gets loader=${Servlet.getClassLoader()}"
println "ServletHolder class gets loader=${ServletHolder.getClassLoader()}"
ServletHolder servletHolder = new ServletHolder(servlet)
context.addServlet(servletHolder,"/*");
server.start();
} catch (Exception e) {
server = null
e.printStackTrace()
return
}
}
}
void stop() {
server.stop()
}
}
When I run:
def store = ObjectStore.getInstance()
println "Startup gets store ID=${store}, class=${System.identityHashCode(store.class)}, loader=${store.class.classLoader}"
def ews = new EmbeddedWebServer().start()
I get the following:
Startup gets store ID=com.metaficient.core.store.ObjectStore@4e9e75f6, class=1237624300, loader=org.codehaus.groovy.tools.RootLoader@303bc257
Thread class loader=groovy.lang.GroovyClassLoader@29abc69
ApplicationServlet gets ID=com.metaficient.fast.scripts.TestServlet@221a5770, class=618337492, loader=org.codehaus.groovy.tools.RootLoader@303bc257
Servlet class gets loader=org.codehaus.groovy.tools.RootLoader@303bc257
ServletHolder class gets loader=sun.misc.Launcher$AppClassLoader@40affc70
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: org.eclipse.jetty.servlet.ServletHolder(com.metaficient.fast.scripts.TestServlet)
at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1481)
at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1397)
at org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite.callConstructor(MetaClassConstructorSite.java:46)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:198)
at com.metaficient.fast.EmbeddedWebServer.start(EmbeddedWebServer.groovy:69)
at com.metaficient.fast.EmbeddedWebServer$start.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
at com.metaficient.fast.scripts.EmbeddedWebServerTest.run(EmbeddedWebServerTest.groovy:33)
at groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:266)
at groovy.lang.GroovyShell.run(GroovyShell.java:229)
at groovy.lang.GroovyShell.run(GroovyShell.java:159)
at groovy.ui.GroovyMain.processOnce(GroovyMain.java:496)
at groovy.ui.GroovyMain.run(GroovyMain.java:311)
at groovy.ui.GroovyMain.process(GroovyMain.java:297)
at groovy.ui.GroovyMain.processArgs(GroovyMain.java:112)
at groovy.ui.GroovyMain.main(GroovyMain.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:108)
at org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:130)
My assumption is that the differing class loaders for ServletHolder and Servlet prevent the selection of the correct constructor on the highlighted line. What I don't understand is why ServletHolder is getting loaded with the App class loader. My understanding is that the loading class class loader would be used (which is RootLoader). I also don't understand how ServletHolder or the Jetty jars could change the class loader before being loaded
Any help much appreciated!