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 バケット内のオブジェクトを一覧表示する同期ページ分割メソッドを示しています。

ページを反復処理する

最初の例は、ページネーターオブジェクトである ListObjectsV2Iterableインスタンスを使用して、 listRes streamメソッドですべてのレスポンスページを反復処理する方法を示しています。コードはレスポンスページをストリーミングし、レスポンスストリームを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 つの例では、 メソッドを呼び出す非同期 DynamoDB クライアントを の取得リクエストlistTablesPaginatorで使用します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

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

POM エントリ

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

Code

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。