Trabaje con resultados paginados mediante la versión 2.x de AWS SDK for Java - AWS SDK for Java 2.x

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Trabaje con resultados paginados mediante la versión 2.x de AWS SDK for Java

Muchas AWS operaciones devuelven resultados paginados cuando el objeto de respuesta es demasiado grande para mostrarlos en una sola respuesta. En la AWS SDK for Java versión 1.0, la respuesta contiene un token que se usa para recuperar la siguiente página de resultados. Por el contrario, la versión AWS SDK for Java 2.x cuenta con métodos de autopaginación que permiten realizar múltiples llamadas de servicio para obtener automáticamente la siguiente página de resultados. Solo tiene que escribir el código que procesa los resultados. La paginación automática está disponible para clientes síncronos y asíncronos.

nota

Estos fragmentos de código asumen que entiende los fundamentos del uso del SDK, y ha configurado su entorno con acceso de inicio de sesión único.

Paginación síncrona

En los ejemplos siguientes, se muestran métodos de paginación síncrona para obtener una lista de los objetos en un bucket de Amazon S3 .

Iterar sobre páginas

El primer ejemplo muestra el uso de un objeto listRes paginador, una ListObjectsV2Iterableinstancia, para recorrer en iteración todas las páginas de respuesta con el método. stream El código recorre las páginas de respuesta, convierte el flujo de respuesta en un flujo de S3Object contenido y, a continuación, procesa el contenido del objeto. Amazon S3

Las importaciones siguientes se aplican a todos los ejemplos de esta sección de paginación síncrona.

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()));

Consulte el ejemplo completo en GitHub.

Iterar sobre objetos

Los ejemplos siguientes muestran formas de recorrer en iteración los objetos devueltos en la respuesta en lugar de las páginas de la respuesta. El método contents de clase ListObjectsV2Iterable devuelve un SdkIterable que proporciona varios métodos para procesar los elementos de contenido subyacentes.

Usar un stream

El siguiente fragmento de código utiliza el método stream sobre el contenido de la respuesta para recorrer en iteración la colección de elementos paginados.

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

Consulte el ejemplo completo en GitHub.

Usar un buble for-each

Como SdkIterable amplía la interfaz de Iterable, puede procesar el contenido como cualquier otro Iterable. El siguiente fragmento de código utiliza un bucle estándar for-each para recorrer en iteración el contenido de la respuesta.

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

Consulte el ejemplo completo en GitHub.

Paginación manual

Si su caso de uso lo requiere, la paginación manual seguirá estando disponible. Utilice el siguiente token del objeto de respuesta para las solicitudes posteriores. En este ejemplo se usa un bucle 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(); }

Consulte el ejemplo completo en GitHub.

Paginación asíncrona

Los siguientes ejemplos muestran los métodos de paginación asíncrona para enumerar tablas. DynamoDB

Recorrer en iteración páginas de nombres de tablas

Los dos ejemplos siguientes utilizan un cliente DynamoDB asíncrono que llama listTablesPaginator al método con una solicitud para obtener un. ListTablesPublisher ListTablesPublisherimplementa dos interfaces, lo que proporciona muchas opciones para procesar las respuestas. Analizaremos los métodos de cada interfaz.

Utilizar un Subscriber.

En el ejemplo de código siguiente se muestra cómo procesar los resultados paginados mediante la interfaz org.reactivestreams.Publisher implementada por ListTablesPublisher. Para obtener más información sobre el modelo de flujos reactivos, consulte el GitHub repositorio de flujos reactivos.

Las importaciones siguientes se aplican a todos los ejemplos de esta sección de paginación asíncrona.

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;

El siguiente código adquiere una instancia 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);

El código siguiente utiliza una implementación anónima de org.reactivestreams.Subscriber para procesar los resultados de cada página.

El método onSubscribe llama al método Subscription.request para iniciar las solicitudes de datos del publicador. Este método debe llamarse para empezar a obtener datos del publicador.

El método onNext del suscriptor procesa una página de respuesta accediendo a todos los nombres de las tablas e imprimiendo cada una de ellas. Una vez procesada la página, se solicita otra página al publicador. Este es el método que se llama repetidamente hasta que se recuperan todas las páginas.

El método onError se desencadena si se produce un error al recuperar los datos. Por último, se llama al método onComplete cuando se han solicitado todas las páginas.

// 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. } });

Consulta el ejemplo completo en. GitHub

Utilizar un Consumer.

La interfaz SdkPublisher que ListTablesPublisher implementa tiene un método subscribe que toma un Consumer y devuelve un CompletableFuture<Void>.

El método subscribe de esta interfaz se puede utilizar para casos de uso simples en los que un org.reactivestreams.Subscriber puede resultar demasiado recargado. Como el siguiente código consume cada página, llama al método tableNames en cada una de ellas. El método tableNames devuelve un java.util.List de nombres de tablas de DynamoDB que se procesan con el método forEach.

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

Consulte el ejemplo completo en GitHub.

Recorrer en iteración nombres de tablas

Los ejemplos siguientes muestran formas de recorrer en iteración los objetos devueltos en la respuesta en lugar de las páginas de la respuesta. De forma similar al ejemplo síncrono de Amazon S3 mostrado anteriormente con su método contents, la clase de resultados asíncrona de DynamoDB, ListTablesPublisher dispone del método de conveniencia tableNames para interactuar con la colección de elementos subyacente. El tipo devuelto del método tableNames es un SdkPublisher que se puede usar para solicitar elementos en todas las páginas.

Utilizar un Subscriber.

El código siguiente adquiere un SdkPublisher de las colecciones subyacentes de nombres de tablas.

// 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();

El código siguiente utiliza una implementación anónima de org.reactivestreams.Subscriber para procesar los resultados de cada página.

El método del suscriptor onNext procesa un elemento individual de la colección. En este caso, es el nombre de una tabla. Una vez procesada la página, se solicita otra página al publicador. Este es el método que se llama repetidamente hasta que se recuperan todas las páginas.

// 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() { } });

Consulte el ejemplo completo en GitHub.

Utilizar un Consumer.

En el ejemplo siguiente, se utiliza el método subscribe de SdkPublisher que toma un Consumer a para procesar cada elemento.

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

Consulte el ejemplo completo en GitHub.

Usar una biblioteca de terceros

Puede utilizar otras bibliotecas de terceros en lugar de implementar un suscriptor personalizado. Este ejemplo demuestra el uso de RxJava, pero se puede utilizar cualquier biblioteca que implemente las interfaces de flujo reactivo. Consulte la página RxJava wiki GitHub para obtener más información sobre esa biblioteca.

Para utilizar la biblioteca, añádala como una dependencia. Si utiliza Maven, el ejemplo muestra el fragmento de POM que se debe utilizar.

Entrada de POM

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

Código

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);

Consulte el ejemplo completo en GitHub.