概要
実際に遭遇した不具合のトラブルシューティングの内容をメモしておきます。
今回は、mavenの依存性に関するトラブルです。
事象
jerseyを使って、REST APIを提供しているアプリケーション。
このアプリケーションに、jasperreportでpdf帳票を出す機能を追加したところ、jerseyがAPIのリクエストに対し、レスポンスを返せなくなってしまいました。
送られてきたJSONを解釈できなくなっていたようです。
システムログには、NoSuchMethodErrorが吐き出されていました。
重大: java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.ObjectWriter.getConfig()Lcom/fasterxml/jackson/databind/SerializationConfig;
at com.fasterxml.jackson.jaxrs.json.JsonEndpointConfig.forWriting(JsonEndpointConfig.java:45)
at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider._configForWriting(JacksonJsonProvider.java:223)
at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider._configForWriting(JacksonJsonProvider.java:45)
:
原因
犯人
com.fasterxml.jackson.core:jackson-databind
このjarが、2.8.4から2.1.4にダウングレードされていました。
ver.2.1.4には、com.fasterxml.jackson.databind.ObjectWriterにgetConfig()というメソッドが存在せず、NoSuchMethodErrorになってしまった、と。
jackson-databindはなぜダウングレードしたのか
jasperreportsを使うため、pom.xmlに下記の依存関係を追加していました。
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.4.3</version>
</dependency>
これにより、従来はjerseyの依存関係として追加されていたjackson-databindが、jasperreportsの依存関係になってしまったのです。
↓pomにjasperreportsを追加する前の依存関係1
+- org.glassfish.jersey.media:jersey-media-json-jackson:jar:2.25:compile
| +- org.glassfish.jersey.core:jersey-common:jar:2.25:compile
| | +- javax.annotation:javax.annotation-api:jar:1.2:compile
| | +- org.glassfish.jersey.bundles.repackaged:jersey-guava:jar:2.25:compile
| | +- org.glassfish.hk2:hk2-api:jar:2.5.0-b30:compile
| | | +- org.glassfish.hk2:hk2-utils:jar:2.5.0-b30:compile
| | | \- org.glassfish.hk2.external:aopalliance-repackaged:jar:2.5.0-b30:compile
| | +- org.glassfish.hk2.external:javax.inject:jar:2.5.0-b30:compile
| | +- org.glassfish.hk2:hk2-locator:jar:2.5.0-b30:compile
| | \- org.glassfish.hk2:osgi-resource-locator:jar:1.0.1:compile
| +- org.glassfish.jersey.ext:jersey-entity-filtering:jar:2.25:compile
| +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.8.4:compile
| | +- com.fasterxml.jackson.core:jackson-core:jar:2.8.4:compile
| | \- com.fasterxml.jackson.core:jackson-databind:jar:2.8.4:compile
| +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.8.4:compile
| | \- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.8.4:compile
| \- com.fasterxml.jackson.core:jackson-annotations:jar:2.8.4:compile
↓pomにjasperreportsを追加した後の依存関係1
+- org.glassfish.jersey.media:jersey-media-json-jackson:jar:2.25:compile
| +- org.glassfish.jersey.core:jersey-common:jar:2.25:compile
| | +- javax.annotation:javax.annotation-api:jar:1.2:compile
| | +- org.glassfish.jersey.bundles.repackaged:jersey-guava:jar:2.25:compile
| | +- org.glassfish.hk2:hk2-api:jar:2.5.0-b30:compile
| | | +- org.glassfish.hk2:hk2-utils:jar:2.5.0-b30:compile
| | | \- org.glassfish.hk2.external:aopalliance-repackaged:jar:2.5.0-b30:compile
| | +- org.glassfish.hk2.external:javax.inject:jar:2.5.0-b30:compile
| | +- org.glassfish.hk2:hk2-locator:jar:2.5.0-b30:compile
| | \- org.glassfish.hk2:osgi-resource-locator:jar:1.0.1:compile
| +- org.glassfish.jersey.ext:jersey-entity-filtering:jar:2.25:compile
| +- com.fasterxml.jackson.jaxrs:jackson-jaxrs-base:jar:2.8.4:compile
| \- com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:jar:2.8.4:compile
| \- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.8.4:compile
+- net.sf.jasperreports:jasperreports:jar:6.4.3:compile
| +- commons-collections:commons-collections:jar:3.2.2:compile
| +- commons-digester:commons-digester:jar:2.1:compile
| +- org.jfree:jcommon:jar:1.0.23:compile
| +- org.jfree:jfreechart:jar:1.0.19:compile
| +- org.eclipse.jdt.core.compiler:ecj:jar:4.4.2:compile
| +- org.codehaus.castor:castor-xml:jar:1.3.3:compile
| | +- org.codehaus.castor:castor-core:jar:1.3.3:compile
| | +- commons-lang:commons-lang:jar:2.6:compile
| | +- javax.inject:javax.inject:jar:1:compile
| | +- stax:stax:jar:1.2.0:compile
| | | \- stax:stax-api:jar:1.0.1:compile
| | \- javax.xml.stream:stax-api:jar:1.0-2:compile
| +- com.fasterxml.jackson.core:jackson-core:jar:2.1.4:compile
| +- com.fasterxml.jackson.core:jackson-databind:jar:2.1.4:compile
| +- com.fasterxml.jackson.core:jackson-annotations:jar:2.1.4:compile
| +- org.apache.lucene:lucene-core:jar:4.5.1:compile
| +- org.apache.lucene:lucene-analyzers-common:jar:4.5.1:compile
| +- org.apache.lucene:lucene-queryparser:jar:4.5.1:compile
| | +- org.apache.lucene:lucene-queries:jar:4.5.1:compile
| | \- org.apache.lucene:lucene-sandbox:jar:4.5.1:compile
| | \- jakarta-regexp:jakarta-regexp:jar:1.4:compile
| +- org.olap4j:olap4j:jar:0.9.7.309-JS-3:compile
| \- com.google.zxing:core:jar:3.2.1:compile
対応方法
pom.xmlのjasperreportsの定義部分にexclusion要素を追加しました。
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.4.3</version>
<exclusions>
<exclusion>
<artifactId>*</artifactId>
<groupId>com.fasterxml.jackson.core</groupId>
</exclusion>
</exclusions>
</dependency>
「jasperreportsは欲しいけど、その依存関係であるjackson-coreはいらないよ」という指定になります。
jasperreportsからjackson-coreを除外した事で、再びjerseyの依存関係としてver.2.8.4を取ってくるようになりました。
補足
artifactIdを*(アスタリスク)にすると、『groupIdが「com.fasterxml.jackson.core」のやつ全部!』を意味します。
「com.fasterxml.jackson.core:jackson-databind」が直接の犯人だったので、artifactIdには「jackson-databind」と書いてもOKでした。
ただ、よく見ると、同じ「com.fasterxml.jackson.core」に属するjarは全てver2.1.4にダウングレードしていたので、全部まとめて従来のバージョンに戻す事にしました。知らないうちに、何か影響が出ている可能性もありますので。
再発防止
今回pom.xmlに対して加えた変更は、新しい依存関係を追加しただけです。
なので、既存のjarに対して影響が出るとは思ってもいませんでした。
防止するのが難しい部類に入りますね。
今後、依存関係の追加時には既存jarのバージョンが変わっていないか確認する必要がありそうです。
ビルド用のスクリプトに、前回ビルド時のjarバージョンと比較するような処理を入れようと思っています。
何か他にいい方法を知っている方、教えて頂けると助かります。
#参考にしたサイト
POM Reference