使用Jetty 6加载webapp JAR的麻烦

时间:2013-03-07 02:22:03

标签: jersey jetty classloader

我有一个Jetty 6.1.9环境,我试图引导一个'爆炸'的WAR样式上下文,但是,我得到NoClassDefFoundError错误。

Jetty env是这样引导的:

public class MyServer {

  public static void main(String[] argv) {

         jetty_default = jetty_default + "/web-content/jetty-6.1.9";
         String jetty_home = System.getProperty("jetty.home", jetty_default);

         Server server = new Server();
         Connector connector = new SelectChannelConnector();
         connector.setPort(7895);

         server.setConnectors(new Connector[]{connector});

         WebAppContext myAppCxt= new WebAppContext();
         myAppCxt.setContextPath("/foo");
         myAppCxt.setWar(jetty_home + "/wardirs/myApp");

         myAppCxt.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");

         myAppCxt.setInitParams(initParamsMaps);
         myAppCxt.setTempDirectory(aTmpDir);

         server.setHandler(processingNodeAppCxt);
         server.start();

  }

wardirs / myApp的布局看起来像这样

  • wardirs
    • 对myApp
      • WEB-INF
        • LIB \  jdom.jar
        • 的web.xml

我收到错误的类是在foo.jar中。

它也感觉Jetty在WEB-INF / lib目录中找到了JAR,因为在启动服务器后foo.jar被锁定(我尝试删除它),当我杀死服务器时它就会解锁。

如果我手动将JAR放在运行MyServer主方法的java cmd行的类路径上,那么一切正常,但是,我希望这些JAR存在于WEB-INF \ lib目录中并自动拾取它们应该是。

实际例外是:

Mar 06, 2013 9:07:25 PM sun.reflect.NativeMethodAccessorImpl invoke0
SEVERE: /foo/api/process
java.lang.NoClassDefFoundError: org/jdom/Content
    at com.foo.MyManager$Status.createICProcessor(MyManager.java:231)
    at com.foo.myApp.Api.process(API.java:xxx)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:149)
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:67)
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:259)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:71)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:990)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:941)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:932)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:384)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:451)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:632)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    at org.mortbay.jetty.Server.handle(Server.java:324)
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:842)
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
    at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:450)
Caused by: java.lang.ClassNotFoundException: org.jdom.Content
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    ... 35 more

我能想到的唯一另一件事就是因为这感觉就像一个类加载器上下文问题,堆栈跟踪顶行中引用的MyManager正在自己的线程中运行,该线程由webapp的ServletContextListener启动,如下所示: / p>

        myMgrThread = new Thread(myManager);
        long myMgrThreadId = myMgrThread.getId();
        myMgrThread .setName("MyApp_MyMgr-" + myMgrThreadId);
        myMgrThread .setPriority(Thread.NORM_PRIORITY);
        myMgrThread .setDaemon(true);
        myMgrThread .start();

2 个答案:

答案 0 :(得分:0)

根据您的项目布局和该堆栈跟踪,它在com.foo.myApp.Api中找到了com.foo.MyManagerWEB-INF/lib/foo.jar就好了,但找不到org.jdom.Content

org.jdom.Content中是否有wEB-INF/lib/foo.jar?或者在类似的文件中你没有提到像WEB-INF/lib/jdom.jar?或者您希望从父类加载器中找到org.jdom.Content(换句话说,从MyServer类开始的任何类加载器)?

答案 1 :(得分:0)

我想我回答了自己的问题。正在运行的IDE项目不会将'webapp'.class文件移动到“$ jetty_home / wardirs / myApp / WEB-INF / classes”中,正如人们对servlet规范所期望的那样。相反,它将它们包含在调用MyServer.main的类路径中。

当我将应用程序类复制到“$ jetty_home / wardirs / myApp / WEB-INF / classes”时,NOCLASSDEFERROR就消失了。所以现在这些类是WEB-INF / classes,并且在类路径上调用main。

正如您可能在这里告诉的那样,这个项目没有Webapp和容器之间的关注点分离。应用程序和码头的所有类和JARS都被放在一起并且“有效”。我一直试图将事情分开,以便webapp类和依赖的JAR明确分开,例如。引入一个ServletContextListener来移动以前从'main'引导的webapp代码,将JAR移动到WEB-INF / lib等。这就像试图从你的头发中嚼口香糖。