4

Atmosphere サーブレットを使用したテスト WebSocket アプリケーションでは、次の例外が発生します。

SEVERE: Servlet.service() for servlet AtmosphereServlet threw exception
java.lang.ClassNotFoundException: javax.servlet.AsyncContext
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1645)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491)
    at org.atmosphere.cpr.AtmosphereServlet.doPost(AtmosphereServlet.java:191)
    at org.atmosphere.cpr.AtmosphereServlet.doGet(AtmosphereServlet.java:177)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)

以下の投稿から、これは Servlet 3.0 よりも古い Servlet コンテナーのバージョンが原因である可能性があることを理解しています。

ClassNotFoundException: Jetty hello world の javax.servlet.AsyncContext

ClassNotFoundException: eclipse の Jetty hello world の javax.servlet.AsyncContext

Grails プロジェクト - サーブレット呼び出し - ClassNotFoundException: javax.servlet.AsyncContext

ただし、アプリケーションは Tomcat7 で実行されており、次の依存関係が pom.xml に追加されています。

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

プロジェクト内の他のすべての依存関係を確認しましたが、サーブレットに関連するものは他に見つかりませんでした。それでも例外が発生します。

質問:アプリケーションで実際に使用されている jar ファイルを見つけるにはどうすればよいですか? 古いバージョンの使用を引き起こしている依存関係を見つける方法は?

4

2 に答える 2

3

次のようにして、最終的に依存関係の競合を解決することができました。

アプリケーションで使用される jar ファイルを見つけるために、以下の単純なコードを使用しました。

public void listJarFilesAndClassVersions() {    
    Class classToCheck = javax.servlet.ServletRequestWrapper.class;
    URL location = classToCheck.getResource('/'
        + classToCheck.getName().replace('.', '/') + ".class");

    System.out.println(location.toString());

    for(Package p : Package.getPackages()) {
        if (p.getName().startsWith("javax.servlet")) {
            System.out.println("Class: " + p.getName()
                + ", version: " + p.getSpecificationVersion());
        }
    }
}

クラスjavax.servlet.ServletRequestWrapperが選択されたのは、古いServlet 2.5に存在するためです。

上記のスクリプトを実行すると、次のようになります。

jar:file:/C:/Users/[username]/.m2/repository/org/apache/tomcat/servlet-api/6.0.29/servlet-api-6.0.29.jar!/javax/servlet/ServletRequestWrapper.class
Class: javax.servlet.jsp, version: 2.1
Class: javax.servlet, version: 2.5
Class: javax.servlet.http, version: null

そのため、最初にバージョン 2.5 のサーブレットが使用されていることを確認し、次に「不良」jar が tomcat ディレクトリの下の maven リポジトリにあることを確認します。

短い再調査の後、最終的にその根本的な原因を見つけることができました.mavenアプリケーションをデプロイして実行するときは、Tomcatの具体的なバージョンを指定する必要があります.そうしないと、mavenはバージョン6のtomcatのライブラリを使用します.変更する

mvn -Dmaven.tomcat.port=8080 tomcat:run-war

mvn -Dmaven.tomcat.port=8080 tomcat7:run-war

上記のスクリプトを実行すると、次の結果が得られます。

jar:file:/C:/Users/[username]/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/7.0.47/tomcat-embed-core-7.0.47.jar!/javax/servlet/ServletRequestWrapper.class
Class: javax.servlet.jsp, version: 2.2
Class: javax.servlet, version: 7.0
Class: javax.servlet.http, version: 7.0
Class: javax.servlet.annotation, version: 7.0
Class: javax.servlet.descriptor, version: 7.0

同じ問題に直面している他の人に役立つことを願っています。

于 2016-12-22T15:36:47.053 に答える
1

私が通常競合を見つける方法は 2 つあります。

  1. Eclipse を使用している場合は、IDE で pom.xml を開き、[依存関係階層] タブに切り替えます。左側のパネルは依存関係ツリーで、右側のパネルは実際に使用される依存関係です。各依存関係の直後は、そのスコープです (例: コンパイル / テスト / ランタイム / 競合のために省略)

ここに画像の説明を入力

  1. ターミナルでコマンドを実行します。mvn dependency:treeEclipse のように依存関係を出力します。
于 2016-12-22T16:04:16.267 に答える