Help us understand the problem. What is going on with this article?

EMR5.7でAmazonDynamoDBClientBuilderが上手く使えない対応

環境

EMRは5.7。
aws-java-sdk-dynamodbのバージョンは下記。

build.sbt
libraryDependencies += "com.amazonaws" % "aws-java-sdk-dynamodb" % "1.11.170"

sbt assembly で固めたFAT-JARをEMR上にデプロイ&実行するとエラーが発生。
ローカルでは上手く動くので原因がわからず少し困った。

事象

EMR5.7にて AmazonDynamoDBClientBuilder を利用すると NoClassDefFoundError
AmazonDynamoDBClientBuilder はパスを通している(FAT-JARに含まれている)ので、ClassNotFoundException では無いだろうと思っていたが、原因が特定できず戸惑った。

エラー1
17/08/14 10:17:39 INFO Client:
    (略)
java.lang.NoClassDefFoundError: Could not initialize class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:58)
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:51)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:323)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:287)
        (略)

しばらく動かしたりログを探すと、IllegalAccessErrorがでていた。
どうやらこれが原因なようだ。

エラー2
17/08/14 11:04:29 INFO Client:
    (略)
java.lang.IllegalAccessError: tried to access class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientConfigurationFactory from class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
        at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder.<clinit>(AmazonDynamoDBClientBuilder.java:27)
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:58)
        at SparkApp$$anonfun$main$1$$anonfun$1.apply(SparkApp.scala:51)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.RDD$$anonfun$mapPartitions$1$$anonfun$apply$23.apply(RDD.scala:797)
        at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
        at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:323)
        at org.apache.spark.rdd.RDD.iterator(RDD.scala:287)

調査

調べるといくつか出てきた。

どうやら、EMR5.7はaws-java-sdkのバージョンが 1.10.75.1 までしか対応していないとのこと。現在(※2017/08/15)は1.11系が出ているので、けっこう古い。というか本当なのか?

ということで、公式のドキュメントを調べると...

AWS SDK for Java が 1.10.75 にアップグレード
* http://docs.aws.amazon.com/ja_jp/emr/latest/ReleaseGuide/emr-whatsnew.html

と書いてあり、1.10.75 までは対応していることは見つけたが、それ以降のバージョンについては述べていない。うーむ、信頼できるのか?

対応

ということで、半信半疑ながらSDKのバージョンをダウングレードした。

build.sbt
libraryDependencies += "com.amazonaws" % "aws-java-sdk-dynamodb" % "1.10.75.1"

そうすると、AmazonDynamoDBClientBuilderが利用できないので、今ではdeplicatedになっているAmazonDynamoDBClientを利用して書き換えすることに。

OLD_dynamodbサンプル.scala
    val client = AmazonDynamoDBClientBuilder.standard
      .withRegion("ap-northeast-1")
      .build
    val dynamoDB = new DynamoDB(client)

こちら↑をすこし編集するのみで動いてくれた。

NEW_dynamodbサンプル.scala
    val client = new AmazonDynamoDBClient()
    client.setRegion(Region.getRegion(Regions.AP_NORTHEAST_1))
    val dynamoDB = new DynamoDB(client)

実行結果

実行すると...
上手く動いてくれた。さすがStackOverFlow!

なぜ IllegalAccessError が出てしまうかだが、EMR上でもaws-java-sdkがロードされていると思うので、かみ合わせが悪いのか?このあたりよく分かっていない。

まとめ

EMRでDynamoDBに書き込む時は、SDKのバージョンに気をつけよう。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away