AWS SDK for Java 2.x を使用してページ分割された結果を処理する - AWS SDK for Java 2.x

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS SDK for Java 2.x を使用してページ分割された結果を処理する

多くの AWS オペレーションは、レスポンスオブジェクトが大きすぎて単一のレスポンスで返せない場合にページ分割された結果を返します。 AWS SDK for Java 1.0 では、レスポンスには結果の次のページを取得するために使用するトークンが含まれています。対照的に、 AWS SDK for Java 2.x には自動ページ分割メソッドがあり、複数のサービス呼び出しを実行して結果の次のページを自動的に取得します。この結果を処理するコードを記述するだけです。自動ページ分割は、同期クライアントと非同期クライアントの両方で使用できます。

注記

これらのコードスニペットは、 の使用の基本SDKを理解し、シングルサインオンアクセス で環境を設定していることを前提としています。

同期ページ割り

次の例は、 Amazon S3 バケット内のオブジェクトを一覧表示する同期ページ分割メソッドを示しています。

ページを反復処理する

最初の例は、 streamメソッドですべてのレスポンスページを繰り返し実行する、 listRes パジネーターオブジェクトであるListObjectsV2Iterableインスタンスの使用を示しています。コードはレスポンスページを経由し、レスポンスストリームをS3Objectコンテンツのストリームに変換し、 Amazon S3 オブジェクトのコンテンツを処理します。

以下のインポートは、この同期ページ分割セクションのすべての例に適用されます。

import java.io.IOException; import java.nio.ByteBuffer; import java.util.Random; import software.amazon.awssdk.core.waiters.WaiterResponse; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; import software.amazon.awssdk.services.s3.model.S3Object; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; import software.amazon.awssdk.services.s3.model.DeleteBucketRequest; import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.CompletedMultipartUpload; import software.amazon.awssdk.services.s3.model.CreateBucketRequest; import software.amazon.awssdk.services.s3.model.CompletedPart; import software.amazon.awssdk.services.s3.model.CreateBucketConfiguration; import software.amazon.awssdk.services.s3.model.UploadPartRequest; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; import software.amazon.awssdk.services.s3.waiters.S3Waiter; import software.amazon.awssdk.services.s3.model.HeadBucketRequest; import software.amazon.awssdk.services.s3.model.HeadBucketResponse;
ListObjectsV2Request listReq = ListObjectsV2Request.builder() .bucket(bucketName) .maxKeys(1) .build(); ListObjectsV2Iterable listRes = s3.listObjectsV2Paginator(listReq); // Process response pages listRes.stream() .flatMap(r -> r.contents().stream()) .forEach(content -> System.out .println(" Key: " + content.key() + " size = " + content.size()));

の完全な例を参照してください GitHub。

オブジェクトを反復処理する

次の例では、レスポンスのページではなく、レスポンスで返るオブジェクトを反復処理する方法を示します。ListObjectsV2Iterable クラスの contents メソッドは、基になるコンテンツ要素を処理する複数のメソッドを提供する SdkIterable を返します。

ストリーミングを使用する

以下のスニペットは、レスポンスコンテンツの stream メソッドを使用して、ページ分割された項目コレクションを反復処理します。

// Helper method to work with paginated collection of items directly. listRes.contents().stream() .forEach(content -> System.out .println(" Key: " + content.key() + " size = " + content.size()));

の完全な例を参照してください GitHub。

for-each ループを使用する

SdkIterableIterable インターフェースを拡張するので、他の Iterable と同じように内容を処理できます。次のスニペットでは、標準の for-each ループを使用してレスポンスの内容を反復処理しています。

for (S3Object content : listRes.contents()) { System.out.println(" Key: " + content.key() + " size = " + content.size()); }

の完全な例を参照してください GitHub。

手動のページ割り

手動のページ分割が必要なユースケースでは、従来どおり手動のページ分割を使用できます。それ以降のリクエストについては、応答オブジェクトの次のトークンを使用します。次の例では while ループを使用します。

ListObjectsV2Request listObjectsReqManual = ListObjectsV2Request.builder() .bucket(bucketName) .maxKeys(1) .build(); boolean done = false; while (!done) { ListObjectsV2Response listObjResponse = s3.listObjectsV2(listObjectsReqManual); for (S3Object content : listObjResponse.contents()) { System.out.println(content.key()); } if (listObjResponse.nextContinuationToken() == null) { done = true; } listObjectsReqManual = listObjectsReqManual.toBuilder() .continuationToken(listObjResponse.nextContinuationToken()) .build(); }

の完全な例を参照してください GitHub。

非同期ページ割り

次の例は、 DynamoDB テーブルを一覧表示する非同期ページ分割方法を示しています。

テーブル名のページを反復処理する

次の 2 つの例では、 を取得するリクエストで listTablesPaginatorメソッドを呼び出す非同期 DynamoDB クライアントを使用しますListTablesPublisher。 は 2 つのインターフェイスListTablesPublisherを実装し、レスポンスを処理する多くのオプションを提供します。各インターフェースのメソッドを見ていきます。

Subscriber を使用する

次のコード例は、ListTablesPublisher で実装された org.reactivestreams.Publisher インターフェイスを使用してページ分割された結果を処理する方法を示しています。リアクティブストリームモデルの詳細については、「リアクティブストリーム GitHub リポジトリ」を参照してください。

以下のインポートは、この非同期ページ分割セクションのすべての例に適用されます。

import io.reactivex.rxjava3.core.Flowable; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import reactor.core.publisher.Flux; import software.amazon.awssdk.core.async.SdkPublisher; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest; import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse; import software.amazon.awssdk.services.dynamodb.paginators.ListTablesPublisher; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException;

次のコードは ListTablesPublisher インスタンスを取得します。

// Creates a default client with credentials and region loaded from the // environment. final DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create(); ListTablesRequest listTablesRequest = ListTablesRequest.builder().limit(3).build(); ListTablesPublisher publisher = asyncClient.listTablesPaginator(listTablesRequest);

次のコードでは、org.reactivestreams.Subscriber の匿名実装を使用して各ページの結果を処理します。

この onSubscribe メソッドでは、Subscription.request メソッドを呼び出して、公開者に対してデータのリクエストを開始します。公開者からデータの取得を開始するには、このメソッドを呼び出す必要があります。

サブスクライバーの onNext メソッドは、すべてのテーブル名にアクセスし、それぞれを出力することでレスポンスページを処理します。ページが処理されると、パブリッシャーに別のページが要求されます。このメソッドは、すべてのページが取得されるまで繰り返し呼び出されます。

データ取得中にエラーが発生すると、onError メソッドがトリガーされます。最後に、すべてのページがリクエストされると、onComplete メソッドが呼び出されます。

// A Subscription represents a one-to-one life-cycle of a Subscriber subscribing // to a Publisher. publisher.subscribe(new Subscriber<ListTablesResponse>() { // Maintain a reference to the subscription object, which is required to request // data from the publisher. private Subscription subscription; @Override public void onSubscribe(Subscription s) { subscription = s; // Request method should be called to demand data. Here we request a single // page. subscription.request(1); } @Override public void onNext(ListTablesResponse response) { response.tableNames().forEach(System.out::println); // After you process the current page, call the request method to signal that // you are ready for next page. subscription.request(1); } @Override public void onError(Throwable t) { // Called when an error has occurred while processing the requests. } @Override public void onComplete() { // This indicates all the results are delivered and there are no more pages // left. } });

の完全な例を参照してください GitHub。

Consumer を使用する

ListTablesPublisher を実装する SdkPublisher インターフェースには、Consumer を受け取って CompletableFuture<Void> を返す subscribe メソッドがあります。

このインターフェースの subscribe メソッドは、org.reactivestreams.Subscriber のオーバーヘッドが大きすぎるような単純なユースケースに使用できます。以下のコードは各ページを使用するため、それぞれの tableNames メソッドを呼び出します。tableNames メソッドは、forEach メソッドで処理される DynamoDB テーブル名 の java.util.List を返します。

// Use a Consumer for simple use cases. CompletableFuture<Void> future = publisher.subscribe( response -> response.tableNames() .forEach(System.out::println));

の完全な例を参照してください GitHub。

テーブル名を反復処理する

次の例では、レスポンスのページではなく、レスポンスで返るオブジェクトを反復処理する方法を示します。前に contents メソッドで示した同期 Amazon S3 の例と同様、DynamoDB 非同期結果クラス、ListTablesPublisher には、基になるアイテムコレクションを操作するための tableNames 便利なメソッドがあります。tableNames メソッドの戻り型は、すべてのページに項目をリクエストできる SdkPublisher です。

Subscriber を使用する

次のコードは、基になるテーブル名のコレクションの SdkPublisher を取得します。

// Create a default client with credentials and region loaded from the // environment. final DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create(); ListTablesRequest listTablesRequest = ListTablesRequest.builder().limit(3).build(); ListTablesPublisher listTablesPublisher = asyncClient.listTablesPaginator(listTablesRequest); SdkPublisher<String> publisher = listTablesPublisher.tableNames();

次のコードでは、org.reactivestreams.Subscriber の匿名実装を使用して各ページの結果を処理します。

サブスクライバーの onNext メソッドはコレクションの個々の要素を処理します。この場合はテーブル名です。テーブル名が処理されると、パブリッシャーから別のテーブル名が要求されます。このメソッドは、すべてのテーブル名が取得されるまで繰り返し呼び出されます。

// Use a Subscriber. publisher.subscribe(new Subscriber<String>() { private Subscription subscription; @Override public void onSubscribe(Subscription s) { subscription = s; subscription.request(1); } @Override public void onNext(String tableName) { System.out.println(tableName); subscription.request(1); } @Override public void onError(Throwable t) { } @Override public void onComplete() { } });

の完全な例を参照してください GitHub。

Consumer を使用する

次の例では、各項目の処理に Consumer を要する SdkPublishersubscribe メソッドを使用しています。

// Use a Consumer. CompletableFuture<Void> future = publisher.subscribe(System.out::println); future.get();

の完全な例を参照してください GitHub。

サードパーティーライブラリを使用する

カスタムの受信者を実装せずに、その他のサードパーティーのライブラリを使用することができます。この例では、 の使用を示していますが RxJava、リアクティブストリームインターフェイスを実装するライブラリを使用することができます。そのライブラリの詳細については、 RxJava の wiki ページ GitHubを参照してください。

このライブラリを使用するには、依存関係として追加します。Maven を使用している場合、この例は使用するPOMスニペットを示しています。

POM エントリ

<dependency> <groupId>io.reactivex.rxjava3</groupId> <artifactId>rxjava</artifactId> <version>3.1.6</version> </dependency>

コード

DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create(); ListTablesPublisher publisher = asyncClient.listTablesPaginator(ListTablesRequest.builder() .build()); // The Flowable class has many helper methods that work with // an implementation of an org.reactivestreams.Publisher. List<String> tables = Flowable.fromPublisher(publisher) .flatMapIterable(ListTablesResponse::tableNames) .toList() .blockingGet(); System.out.println(tables);

の完全な例を参照してください GitHub。