PlayframeworkからAWS SDK for Java 2.0を使用して、DynamoDBを利用したので記録しておきます。
といってもJavaのAWS SDKを使用するだけなので、Scalaはあまり関係ないかも(^_^;)
依存ライブラリ
build.sbt
libraryDependencies += "software.amazon.awssdk" % "aws-sdk-java" % "2.13.27"
DynamoDBに接続する
ダメなケース
以下のようにDynamoDbClientにクレデンシャルを渡して接続すればうまく行くように思ったんだけど、これではダメ。
import software.amazon.awssdk.regions.Region import java.util.HashMap import software.amazon.awssdk.services.dynamodb.DynamoDbClient import software.amazon.awssdk.services.dynamodb.model.{AttributeValue, GetItemRequest} import software.amazon.awssdk.auth.credentials.{AwsSessionCredentials, StaticCredentialsProvider} val dynamodb = DynamoDbClient.builder() .region(Region.AP_NORTHEAST_1) .credentialsProvider( StaticCredentialsProvider.create( AwsSessionCredentials.create(accessKey, secretKey, "") ) ).build()
Execution exception[[DynamoDbException: The security token included in the request is invalid (Service: DynamoDb, Status Code: 400, Request ID: ..., Extended Request ID: null)]]
のようにrequestに無効な認証トークンが含まれるとエラーで伝えられる。
クレデンシャルの正しい指定方法
結論からいうと、AwsSessionCredentials
がダメで代わりにAwsBasicCredentials
でクレデンシャルを指定する。
import software.amazon.awssdk.auth.credentials.{AwsBasicCredentials, StaticCredentialsProvider} val dynamodb = DynamoDbClient.builder() .region(Region.AP_NORTHEAST_1) .credentialsProvider( StaticCredentialsProvider.create( AwsBasicCredentials.create(accessKey, secretKey) ) ).build()
とすることで、DynamoDBのハンドルが取れる。
参考にしたページ
AWS DynamoDB • Alpakka Documentation
公式のドキュメントではAwsBasicCredentials
については触れられておらず、ハマってしまった(^_^;)
AWS 認証情報の提供と取得 - AWS SDK for Java バージョン 2
DynamoDBのテーブル、Itemにアクセスする
例として、プライマリキーid:Int
のuser
テーブルにアクセスします。
取得する条件の定義
id
:25
のItemを取得するには、
val keyToGet = new HashMap[String,AttributeValue]() keyToGet.put("id", AttributeValue.builder().n("25").build())
とJavaのHashMapを作成します。
n
メソッドはDynamoDBのnumber型に値を指定するメソッド(何故か引数の型はString...(^_^;))、string型への問い合わせはs(String)
を使用します。
問い合わせリクエストの作成
上記で作成したHashMapを元に、リクエストを作成します。問い合わせ先のテーブルを指定します。
val request = GetItemRequest.builder().key(keyToGet).tableName("user").build()
DynamoDBへ問い合わせ & 結果の取得
val keyToGet = new HashMap[String,AttributeValue]() keyToGet.put("id", AttributeValue.builder().n("25").build()) val request = GetItemRequest.builder().key(keyToGet).tableName("user").build() val returnedItem = dynamodb.getItem(request) println(returnedItem)
各要素へアクセスするには、
println(returnedItem.item().get("email").s())
のように記述出来ます。
その他の操作は以下を見ながら進めていこうと思う。まだ試してないので、試して記録できそうなら、追記します。
DynamoDB の項目の使用 - AWS SDK for Java バージョン 2
セカンダリインデックスでのSearch & Fetch
セカンダリインデックスを使用したQueryの例。
セカンダリインデックスではなくプライマリキーを指定する場合は、indexName
の指定をせず、keyConditionExpression
にプライマリキーの検索条件を記述すればよい。
val dynamodb = DynamoDbClient.builder().region(Region.AP_NORTHEAST_1).build() val cond = new HashMap[String, AttributeValue]() cond.put(":val", AttributeValue.builder().n("0").build()) val q = QueryRequest.builder() .tableName("yourTableName") .indexName("makedIndexName") .keyConditionExpression( "indexKey = :val") .expressionAttributeValues( cond ) .build() val ret = dynamodb.query(q) println(ret)
※これ演算子が=
以外だとエラーになるんだけどどうやって指定するんだろう...
追記:
QueryRequest.Builder (AWS SDK for Java - 2.13.32)
これ読む限り、
The partition key equality test is required, and must be specified in the following format: partitionKeyName = :partitionkeyval
ソートキーしか演算子いじっちゃダメらしい。
OSに設定済みの環境変数をクレデンシャルとして透過的に使用する。
default profileまたはexport済みのAWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEYAWS
を使用する
credentialsProviderを渡さなければdefaultのprofileまたはexport済みの環境変数を参照する。
val dynamodb = DynamoDbClient.builder().region(Region.AP_NORTHEAST_1).build()
OSに定義してあるaws profileを指定して認証する
val dynamodb = DynamoDbClient.builder() .region(Region.AP_NORTHEAST_1) .credentialsProvider( ProfileCredentialsProvider.create("selectedProfileName") ).build()
この2つが認証取れるのに同じアクセスキーで何故、AwsSessionCredentialsじゃ認証取れないの(^_^;)と無駄にハマってしまいました。