0

「展開された」WAR スタイルのコンテキストをブートストラップしようとしている Jetty 6.1.9 環境がありますが、NoClassDefFoundError エラーが発生します。

Jetty 環境は次のようにブートストラップされます。

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 のレイアウトは次のようになります

  • 病棟
    • マイアプリ
      • WEB-INF
        • lib\jdom.jar
        • web.xml

エラーが発生しているクラスは foo.jar にあります。

また、Jetty が WEB-INF/lib ディレクトリで JAR を見つけているように感じます。これは、サーバーの起動後に foo.jar がロックされ (削除しようとしました)、サーバーを強制終了するとロックが解除されるためです。

MyServer のメイン メソッドを実行する Java コマンド ラインのクラスパスに JAR を手動で配置すると、すべて正常に動作しますが、これらの 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 によって開始された独自のスレッドで実行されていることです。

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

2 に答える 2

0

あなたのプロジェクトのレイアウトとそのスタックトレースによると、それcom.foo.myApp.Apicom.foo.MyManagerあなたWEB-INF/lib/foo.jarの問題なく見つかりましたが、見つけることができませんでしたorg.jdom.Content

あなたorg.jdom.Contentの中に存在しますwEB-INF/lib/foo.jarか?またはあなたが言及していない同様のファイルでWEB-INF/lib/jdom.jarorg.jdom.Contentまたは、親クラスローダー(つまり、MyServerクラスが開始されたクラスローダー)から検索することを期待していますか?

于 2013-03-07T14:17:49.380 に答える
0

私は自分の質問に答えたと思います。これが実行されている IDE プロジェクトは、サーブレットの仕様で期待されるように、「webapp」.class ファイルを「$jetty_home/wardirs/myApp/WEB-INF/classes」に移動しません。代わりに、MyServer.main を呼び出すクラス パスにそれらを含めます。

アプリケーション クラスを「$jetty_home/wardirs/myApp/WEB-INF/classes」にコピーすると、NOCLASSDEFERROR はなくなりました。したがって、クラスは WEB-INF/classes であり、メインを呼び出すクラスパスにあります。

ここでわかるかもしれませんが、このプロジェクトには webapp とコンテナーの間の懸念事項が分離されていません。アプリケーションと jetty のすべてのクラスと JARS が一緒にダンプされ、'動作' します。私は、webapp クラスと依存する JAR が明確に分離されるように、物事をバラバラにしようとしてきました。ServletContextListener を導入して、以前は「メイン」からブートストラップされていた webapp コードを移動し、JAR を WEB-INF/lib などに移動します。チューインガムを髪の毛から取り除こうとするようなものです。

于 2013-03-07T21:40:13.320 に答える