仕事で作っていたアプリケーションでhive-exec
を利用する機会があり、その過程で色々とハマったので解決方法を残しておきます。
java.lang.NoSuchMethodErrorへの対応
アプリケーションを開発し無事にアプリを立ち上げたが実行中にjava.lang.NoSuchMethodError
を吐いて処理が失敗しました。
java.lang.NoSuchMethodError:
'void com.google.common.base.Preconditions.checkArgument(boolean, java.lang.String, java.lang.Object)'
このとき利用していたのがhive-exec-2.3.2-jar
で何故このエラーが出るのかを調べていきます。
まず、jarファイルをダウンロードして中を調べてみるとjarファイルにGoogle guava関連のクラスが含まれていることが分かります。
$ jar tvf hive-exec-2.3.2.jar|grep Preconditions
2059 Thu Nov 09 14:29:18 JST 2017 org/apache/parquet/Preconditions.class
5310 Thu Nov 09 14:29:18 JST 2017 com/google/common/base/Preconditions.class
2704 Thu Nov 09 14:29:20 JST 2017 com/google/common/math/MathPreconditions.class
$ jar tvf hive-exec-2.3.2.jar |grep "guava"
0 Thu Nov 09 14:29:18 JST 2017 META-INF/maven/com.google.guava/
0 Thu Nov 09 14:29:18 JST 2017 META-INF/maven/com.google.guava/guava/
131 Thu Nov 09 14:29:18 JST 2017 META-INF/maven/com.google.guava/guava/pom.properties
5376 Thu Nov 09 14:29:18 JST 2017 META-INF/maven/com.google.guava/guava/pom.xml
今回のエラーは十中八九これが原因と思われました。なので、guava関連のファイルを取り除いたhive-exec.jarを利用すれば問題が解決するように思いました。
幸いなことに、hive-exec
ライブラリは通常のjarファイル以外にもcore.jar
というのが提供されています。
このcore.jar
ファイルは依存ライブラリのクラスが全く入っておらずorg.apache.hive
関連のファイルしか含まれていないjarファイルです。
念の為、このjarファイルをダウンロードして中身を確認してみるとguava関連のクラスが入ってないことが分かります。
$ jar tvf hive-exec-2.3.2-core.jar |grep Preconditions
<no output>
このjarを使えば最初の例外を発生させずにアプリケーションを実行することが出来そうです。
余談: core.jarはいつから提供されているのか? & Why is the core.jar provided?
ここは完全に余談ですがcore.jarはいつから提供されているのかと何故提供されるようになったのかについて見ておきます。
ここ から過去のバージョンをいくつかみていつから提供されているのか調べます。
調べていくとv0.14.0からcore.jarが提供されていました。
次は、この時期のissueを読んで提供された理由を調べていきます。ググったらすぐ該当するissueが見つかりました。
How to use the core.jar in maven, gradle and sbt
さて、core.jarが提供されていることが分かりましたがどうすればこのjarを利用することが出来るのか紹介します。
maven, gradle, sbtの3つでどういう方法でcore.jarを利用するか紹介します。
どれもclassifier
タグかキーワードを入れるだけで簡単に利用することが出来ます。
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>2.3.2</version>
<classifier>core</classifier>
</dependency>
</dependencies>
Gradle
compile("org.apache.hive:hive-exec:2.3.2:core")
or
compile(group:'org.apache.hive', name: 'hive-exec', version: '2.3.2', classifier: 'core')
sbt
libraryDependencies += "org.apache.hive" % "hive-exec" % "2.3.2" classifier "core"
or
"org.apache.hive" % "hive-exec" % "2.3.2" classifier "core"
まとめ
自分のケースではcore.jar
を利用してアプリケーションを再コンパイル・パッケージングして動かして確認したところ例外が発生しなくなり期待通り動作するようになりました。
今回は hive-execを利用する際に起きたトラブルとその解決方法について紹介しました。
自分はこれまでclassifier
されたjarを利用することがなかったのでcore.jar
が提供されている可能性やそのjarファイルの利用方法を調べるのに時間を取られ問題を解決するまでかなりの時間を要しました。
今後同じようなケースがあった場合にサクッとclassifier
されたjarファイルが存在する可能性を調べてデバッグを高速に完了出来るのではないかと思います。
また、このエントリーが他のhive-exec
を利用するユーザーの助けになればと思います。