2017-09-23 3 views
0

私はwebapp-runnerを使用してHerokuで戦争を行っています。私はheroku-maven-pluginバージョン1.2を使用して、次のコマンドでアプリケーションをデプロイします:mvn heroku:deploy-war。最初は、アプリケーションが動作し、すべてのエンドポイントが有効な応答を返します。webapp-runnerで実行中のHeroku web-APIへのAPIコールは、最終的にgoogle.commonでNoSuchMethodError、NoClassDefFoundErrorで失敗します。

2017-09-23T19:19:45.388865+00:00 app[web.1]: SEVERE: Servlet.service() for servlet [jersey-serlvet] in context with path [] threw exception [org.glassfish.jersey.server.ContainerException: java.lang.NoSuchMethodError: com.google.common.base.CharMatcher.ascii()Lcom/google/common/base/CharMatcher;] with root cause 
2017-09-23T19:19:45.388866+00:00 app[web.1]: java.lang.NoSuchMethodError: com.google.common.base.CharMatcher.ascii()Lcom/google/common/base/CharMatcher; 
2017-09-23T19:19:45.388867+00:00 app[web.1]: at com.google.common.io.BaseEncoding$Alphabet.<init>(BaseEncoding.java:453) 
2017-09-23T19:19:45.388868+00:00 app[web.1]: at com.google.common.io.BaseEncoding$Base64Encoding.<init>(BaseEncoding.java:892) 
2017-09-23T19:19:45.388869+00:00 app[web.1]: at com.google.common.io.BaseEncoding.<clinit>(BaseEncoding.java:317) 
...application specific stack trace 

同じAPIへの後続のすべての呼び出しはNoClassDefFoundErrorでの生産:私はアプリは十分な長Herokuのは、寝た後、グアバを呼び出すエンドポイントを呼び出すためにそれを置くためにアイドルを許可している場合しかし、私はNoSuchMethodError受け取ります同じ点

これらの問題は、コンパイル時には存在するが実行時には存在しないことを示唆しているようです。しかし、私は、Webダイナモに-ログインし、グァバジャーが、私は、エンドポイントは、アプリケーションが配備された直後に動作しますが、後でこれらのエラーを生み出す理由を説明するのに苦労しています私のwarfile

my-mbp:TrickServer me$ heroku ps:exec 
Establishing credentials... done 
Connecting to web.1 on ⬢ myapp... 
~ $ cd target/ 
~/target $ ls 
MyApp.war dependency mvn-dependency-list.log tomcat.52079 
~/target $ jar -tf MyApp.war 
...lots of dependencies... 
WEB-INF/lib/google-oauth-client-1.20.0.jar 
WEB-INF/lib/gson-2.2.4.jar 
WEB-INF/lib/guava-23.0.jar  <---guava 
WEB-INF/lib/guava-jdk5-13.0.jar 
...lots more dependencies... 

に含まれていたことを確認しました。私の場合、この動作は、最初に実行されたときや、Herokuが動いている/ guavaのjarfileをクリーンアップしているときよりも、アプリケーションがスリープから復帰したときに、Herokuが潜在的に別のクラスパスを提供している可能性を示唆しているようです。私Procfile

内容:

web: java $JAVA_OPTS -jar target/dependency/webapp-runner.jar --port $PORT --expand-war target/MyApp.war 

Javaは私のウェブダイナモ上で走っプロセス:

~/target $ ps -ef | grep java 
u30439  4  1 0 18:50 ?  00:00:44 java -Xmx300m -Xss512k -Dfile.encoding=UTF-8 -Duser.timezone=UTC -jar target/dependency/webapp-runner.jar --port 52079 target/MyApp.war 
u30439  27  4 0 18:50 ?  00:00:00 bash --login -c java $JAVA_OPTS -jar target/dependency/webapp-runner.jar $WEBAPP_RUNNER_OPTS --port 52079 target/MyApp.war 

アップデート1

私は--expand-war引数で私のWebアプリケーションを呼び出しておりますのでIグアバが存在していることを確認するために、展開されたディレクトリのjarファイルもチェックしました。これは、次のとおりです。

~/target/tomcat.55320/webapps/expanded/WEB-INF/lib $ ls 
...dependencies... 
google-oauth-client-1.20.0.jar 
gson-2.2.4.jar 
guava-23.0.jar 
guava-jdk5-13.0.jar 
...more dependencies... 

アップデート2

私はそれをクラスパスとリソースをプリントアウトするために問題のあるWebサービスに、次のロジックを追加しました:

logger.info("System Classpath: " + System.getProperty("java.class.path")); 
logger.info("Runtime Classes..."); 
    ClassLoader cl = UserService.class.getClassLoader(); 
    URL[] urls = ((URLClassLoader) cl).getURLs(); 
    for(URL url: urls){ 
     logger.info(url.getFile()); 
    } 

次回のエラー私はログを調べて、驚いたことに、グアバのジャーがランタイムのクラスパス上に存在することを発見しました!

2017-09-24T12:07:40.843438+00:00 app[web.1]: [heroku-exec] ERROR: Could not connect to proxy: 
2017-09-24T12:07:40.844145+00:00 app[web.1]: [heroku-exec] ERROR: Too many reconnect attempts. Waiting 30 seconds... 
2017-09-24T12:07:52.671620+00:00 app[web.1]: Sep 24, 2017 12:07:52 PM org.myorg.server.web.services.MyService authenticate 
2017-09-24T12:07:52.671631+00:00 app[web.1]: INFO: System Classpath: target/dependency/webapp-runner.jar 
2017-09-24T12:07:52.671931+00:00 app[web.1]: Sep 24, 2017 12:07:52 PM org.myorg.server.web.services.MyService authenticate 
2017-09-24T12:07:52.671932+00:00 app[web.1]: INFO: Runtime Classes... 
2017-09-24T12:07:52.672277+00:00 app[web.1]: Sep 24, 2017 12:07:52 PM org.myorg.server.web.services.MyService authenticate 
2017-09-24T12:07:52.672279+00:00 app[web.1]: INFO: /app/target/tomcat.28304/webapps/expanded/WEB-INF/classes/ 
.... 
2017-09-24T12:07:52.690304+00:00 app[web.1]: Sep 24, 2017 12:07:52 PM org.myorg.server.web.services.MyService authenticate 
2017-09-24T12:07:52.690306+00:00 app[web.1]: INFO: /app/target/tomcat.28304/webapps/expanded/WEB-INF/lib/google-oauth-client-1.20.0.jar 
2017-09-24T12:07:52.690501+00:00 app[web.1]: Sep 24, 2017 12:07:52 PM org.myorg.server.web.services.MyService authenticate 
2017-09-24T12:07:52.690503+00:00 app[web.1]: INFO: /app/target/tomcat.28304/webapps/expanded/WEB-INF/lib/guava-23.0.jar <--- Guava!!! 
.... 

ここでは何が起こっていますか?これをどのようにデバッグするのですか?

答えて

0

を参照してください、私は私のプログラムは、クラスパス上のグアバの2つの異なるバージョン(guava-23.0.jar & guava-jdk5-13.0.jar)を有していたことを発見しました。デバッグのヒントには、hereが必要でしたが、私にはこれの最後までは十分ではありませんでした。

ClassLoaderを操作する場合、.classオブジェクトに定義されているgetClassLoaderメソッドは、最初にクラスをロードしたClassLoaderへの参照を返すことを覚えておくことが重要です。重複したjarファイルを見つけるには、後でNoSuchMethodErrorで失敗したクラスをロードした同じClassLoaderでclassLoader.getResource("/com/google/common/base/CharMatcher.class")を呼び出すことが重要でした。

後継の場合、競合を引き起こした特定の依存関係はcom.google.api-clientでした。私はそれに以下を追加して解決しましたpom.xml

<dependency> 
    <groupId>com.google.api-client</groupId> 
    <artifactId>google-api-client</artifactId> 
    <version>1.22.0</version> 
    <exclusions> 
     <exclusion> 
      <groupId>com.google.guava</groupId> 
      <artifactId>guava-jdk5</artifactId> 
     </exclusion> 
    </exclusions> 
</dependency> 
関連する問題