

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.

# Uso del AWS SDK for Java 2.x
<a name="using"></a>

En este capítulo se muestra cómo utilizarlos de AWS SDK for Java 2.x forma eficaz. Aprenda a crear clientes de servicio, realizar solicitudes, administrar respuestas y administrar errores. Este capítulo trata sobre programación síncrona y asíncrona, resultados paginados, esperadores para la monitorización de recursos y optimización del rendimiento. 

También se hablará de prácticas recomendadas para la reutilización de clientes, instrucciones de solución de problemas, optimización del inicio de Lambda, compatibilidad con HTTP/2 y configuración de DNS.

**Contents**
+ [

# Realizar Servicio de AWS solicitudes utilizando el AWS SDK for Java 2.x
](work-witih-clients.md)
  + [

## Uso de clientes de servicio para realizar solicitudes
](work-witih-clients.md#using-service-client)
    + [

### Crear un cliente de servicio
](work-witih-clients.md#work-with-clients-create)
    + [

### Configuración predeterminada de cliente
](work-witih-clients.md#using-default-client)
    + [

### Configurar clientes de servicio
](work-witih-clients.md#using-configure-service-clients)
    + [

### Cerrar el cliente de servicio
](work-witih-clients.md#using-closing-client)
  + [

## Hacer solicitudes
](work-witih-clients.md#using-making-requests)
    + [

### Uso de solicitudes para anular la configuración de clientes
](work-witih-clients.md#using-override-client-config-request)
  + [

## Tratamiento de respuestas
](work-witih-clients.md#using-handling-responses)
+ [

# Programación asincrónica mediante AWS SDK for Java 2.x
](asynchronous.md)
  + [

## Uso de API de cliente asincrónicas
](asynchronous.md#basics-async-non-streaming)
  + [

## Administración de streaming en métodos asincrónicos
](asynchronous.md#basics-async-streaming)
  + [

## Configuración de opciones asincrónicas avanzadas
](asynchronous.md#advanced-operations)
+ [

# Mejores prácticas para usar el AWS SDK for Java 2.x
](best-practices.md)
  + [

## Prevención del bloqueo de solicitudes configurando tiempos de espera de la API
](best-practices.md#bestpractice5)
  + [

## Mejora del rendimiento reutilizando clientes de servicio
](best-practices.md#bestpractice1)
  + [

## Prevención de pérdidas de recursos cerrando los clientes de servicio no utilizados
](best-practices.md#bestpractice-close-client)
  + [

## Prevención del agotamiento de grupos de conexiones cerrando flujos de entrada
](best-practices.md#bestpractice2)
  + [

## Optimización del rendimiento de HTTP para la carga de trabajo de la aplicación
](best-practices.md#bestpractice3)
  + [

## Mejora del rendimiento de SSL con OpenSSL para clientes asincrónicos
](best-practices.md#bestpractice4)
  + [

## Monitorización del rendimiento de las aplicaciones con métricas del SDK
](best-practices.md#bestpractice6)
+ [

# Manejo de errores en el AWS SDK for Java 2.x
](handling-exceptions.md)
  + [

## ¿Por qué excepciones no controladas?
](handling-exceptions.md#why-unchecked-exceptions)
  + [

## AwsServiceException (y subclases)
](handling-exceptions.md#sdkserviceexception-and-subclasses)
  + [

## SdkClientException
](handling-exceptions.md#sdkclientexception)
  + [

## Excepciones y comportamiento de reintentos
](handling-exceptions.md#retried-exceptions)
+ [

# Uso de resultados paginados en la versión 2.x AWS SDK para Java
](pagination.md)
  + [

## Paginación síncrona
](pagination.md#synchronous-pagination)
    + [

### Iterar sobre páginas
](pagination.md#iterate-pages)
    + [

### Iterar sobre objetos
](pagination.md#iterate-objects)
      + [

#### Usar un stream
](pagination.md#use-a-stream)
      + [

#### Usar un buble for-each
](pagination.md#for-loop)
    + [

### Paginación manual
](pagination.md#manual-pagination)
  + [

## Paginación asíncrona
](pagination.md#asynchronous-pagination)
    + [

### Recorrer en iteración páginas de nombres de tablas
](pagination.md#iterate-pages-async)
      + [

#### Utilizar un `Subscriber`.
](pagination.md#use-a-subscriber)
      + [

#### Utilizar un `Consumer`.
](pagination.md#id1pagination)
    + [

### Recorrer en iteración nombres de tablas
](pagination.md#iterate-objects-async)
      + [

#### Utilizar un `Subscriber`.
](pagination.md#id2)
      + [

#### Utilizar un `Consumer`.
](pagination.md#for-loop-async)
    + [

### Usar una biblioteca de terceros
](pagination.md#use-third-party-library)
+ [

# Utilizando camareros en el AWS SDK for Java 2.x
](waiters.md)
  + [

## Requisitos previos
](waiters.md#prerequisiteswaiters)
  + [

## Uso de esperadores
](waiters.md#id1waiters)
    + [

### Programación asíncrona
](waiters.md#synchronous-programming)
    + [

### Programación asíncrona
](waiters.md#asynchronous-programming)
  + [

## Configurar los esperadores
](waiters.md#configuring-waiters)
    + [

### Configurar un esperador
](waiters.md#configure-a-waiter)
    + [

### Anular la configuración de una solicitud específica
](waiters.md#override-configuration-for-a-specific-request)
  + [

## Ejemplos de código
](waiters.md#code-examples)
+ [

# Solución de problemas FAQs
](troubleshooting.md)
  + [

## ¿Cómo puedo corregir el error “`java.net.SocketException`: Connection reset” o “server failed to complete the response”?
](troubleshooting.md#faq-socketexception)
  + [

## ¿Cómo puedo corregir “tiempo de espera de conexión”?
](troubleshooting.md#faq-connection-timeout)
  + [

## ¿Cómo puedo corregir “`java.net.SocketTimeoutException`: Read timed out”?
](troubleshooting.md#faq-socket-timeout)
  + [

## ¿Cómo puedo corregir el error “Unable to execute HTTP request: Timeout waiting for connection from pool”?
](troubleshooting.md#faq-pool-timeout)
  + [

## ¿Cómo puedo corregir `NoClassDefFoundError`, `NoSuchMethodError` o `NoSuchFieldError`?
](troubleshooting.md#faq-classpath-errors)
  + [

## ¿Cómo puedo corregir un error “`SignatureDoesNotMatch`” o un error “The request signature we calculated does not match the signature you provided”?
](troubleshooting.md#faq-signature-does-not-match-error)
  + [

## ¿Cómo puedo solucionar el error “`java.lang.IllegalStateException`: Connection pool shut down”?
](troubleshooting.md#faq-connection-pool-shutdown-exception)
  + [

## ¿Cómo puedo corregir el error «No se pueden cargar las credenciales de ninguno de los proveedores de la cadena AwsCredentialsProviderChain»?
](troubleshooting.md#faq-credentials-provider-chain)
    + [

### Problemas y soluciones comunes
](troubleshooting.md#faq-cred-provider-chain-common-causes-and-solutions)
      + [

#### Revise la configuración de sus credenciales
](troubleshooting.md#faq-cred-provider-chain-check-config)
        + [

##### Para instancias de Amazon EC2
](troubleshooting.md#faq-cred-check-ec2)
        + [

##### Para entornos de contenedores
](troubleshooting.md#faq-cred-check-container-env)
        + [

##### Para desarrollo local
](troubleshooting.md#faq-cred-check-local-dev)
        + [

##### Para federación de identidades web
](troubleshooting.md#faq-cred-check-web-id-federation)
      + [

#### Problemas de conectividad de red o de proxy
](troubleshooting.md#faq-credentials-provider-chain-network-issues)
+ [

# Reduzca el tiempo de inicio del SDK para AWS Lambda
](lambda-optimize-starttime.md)
  + [

## Utilice un cliente HTTP AWS basado en CRT
](lambda-optimize-starttime.md#lambda-quick-url)
  + [

## Eliminar las dependencias del cliente HTTP no utilizadas
](lambda-optimize-starttime.md#lambda-quick-remove-deps)
  + [

## Configurar los clientes de servicio para abreviar las búsquedas
](lambda-optimize-starttime.md#lambda-quick-clients)
  + [

## Inicializar el cliente de SDK fuera del controlador de la función de Lambda
](lambda-optimize-starttime.md#lambda-quick-initialize)
  + [

## Minimizar la inyección de dependencias
](lambda-optimize-starttime.md#lambda-quick-di)
  + [

## Utilice una segmentación por arquetipo de Maven AWS Lambda
](lambda-optimize-starttime.md#lambda-quick-maven)
  + [

## Considere Lambda SnapStart para Java
](lambda-optimize-starttime.md#lambda-quick-snapstart)
  + [

## Cambios en la versión 2.x que afectan al tiempo de startup
](lambda-optimize-starttime.md#example-client-configuration)
  + [

## Recursos adicionales
](lambda-optimize-starttime.md#lambda-quick-resources)
+ [

# Implemente `ContentStreamProvider` en el AWS SDK for Java 2.x
](content-stream-provider.md)
  + [

## Utilice `mark()` y `reset()`
](content-stream-provider.md#csp-impl-mark-reset)
  + [

## Uso de almacenamiento en búfer si `mark()` y `reset()` no están disponibles
](content-stream-provider.md#csp-impl-unsupported-streams)
  + [

## Creación de nuevos flujos
](content-stream-provider.md#csp-impl-new-stream)
+ [

# Configurar el TTL de JVM para las búsquedas de nombres DNS
](jvm-ttl-dns.md)
  + [

## Cómo configurar el TTL de JVM
](jvm-ttl-dns.md#how-to-set-the-jvm-ttl)
    + [

### Opción 1: configúrelo mediante programación en su aplicación
](jvm-ttl-dns.md#set-ttl-programmatically)
    + [

### Opción 2: configúrelo en el archivo java.security
](jvm-ttl-dns.md#set-ttl-java-security-file)
    + [

### Opción 3: Utilice la opción alternativa de propiedades del sistema JDK (línea de comandos)
](jvm-ttl-dns.md#set-ttl-system-property)
+ [

# Trabajar con HTTP/2 en el AWS SDK para Java
](http2.md)

# Realizar Servicio de AWS solicitudes utilizando el AWS SDK for Java 2.x
<a name="work-witih-clients"></a>

## Uso de clientes de servicio para realizar solicitudes
<a name="using-service-client"></a>

Tras completar los pasos de [Configuración del SDK](setup.md) y comprender cómo [configurar los clientes de servicio](configuring-service-clients.md), estará listo para realizar solicitudes a AWS servicios como Amazon S3, Amazon DynamoDB, AWS Identity and Access Management Amazon EC2, etc.

### Crear un cliente de servicio
<a name="work-with-clients-create"></a>

Para realizar una solicitud a un Servicio de AWS, primero debe crear una instancia de un cliente de servicio para ese servicio mediante el método estático de fábrica,. `builder()` El método `builder()` devuelve un objeto `builder` que permite personalizar el cliente de servicio. Los métodos setter Fluent devuelven el objeto `builder` para que pueda encadenar fácilmente las llamadas a los métodos y para simplificar la lectura del código. Después de configurar las propiedades que desee, puede llamar al método `build()` para crear el cliente.

A modo de ejemplo, el siguiente fragmento de código crea una instancia de un objeto `Ec2Client` como cliente de servicio para Amazon EC2.

```
Region region = Region.US_WEST_2;
Ec2Client ec2Client = Ec2Client.builder()
        .region(region)
        .build();
```

**nota**  
Los clientes de servicios del SDK son seguros para subprocesos. Para obtener el máximo desempeño, trátelos como objetos de larga duración. Cada cliente tiene su propio recurso de grupo de conexiones que se libera cuando el cliente recopila los elementos no utilizados.  
Un objeto cliente de servicio es inmutable, por lo que deberá crear un nuevo cliente para cada servicio al que haga peticiones, o si desea utilizar una configuración diferente para realizar peticiones al mismo servicio.  
No es necesario especificarlo `Region` en el generador de clientes de AWS servicios para todos los servicios; sin embargo, se recomienda establecer la región de las llamadas a la API que realice en sus aplicaciones. Para obtener más información, consulte la [Selección de regiones de AWS](region-selection.md).

### Configuración predeterminada de cliente
<a name="using-default-client"></a>

Los creadores de clientes tienen otro método de fábrica denominado `create()`. Este método crea un servicio cliente con la configuración predeterminada. Utiliza la [cadena de proveedores predeterminada](credentials-chain.md) para cargar las credenciales y la [cadena Región de AWS de proveedores predeterminada](region-selection.md#automatically-determine-the-aws-region-from-the-environment). Si las credenciales o la región no se pueden determinar a partir del entorno en el que se ejecuta la aplicación, la llamada a `create` produce un error. Consulte [Uso de credenciales](credentials.md) y [Selección de regiones](region-selection.md) para obtener más información acerca de cómo el SDK determinan las credenciales y la región.

A modo de ejemplo, el siguiente fragmento de código crea una instancia de un objeto `DynamoDbClient` como cliente de servicio para Amazon DynamoDB:

```
DynamoDbClient dynamoDbClient = DynamoDbClient.create();
```

### Configurar clientes de servicio
<a name="using-configure-service-clients"></a>

Para obtener información detallada sobre cómo configurar clientes de servicio, consulte [Configuración externa de clientes](configuring-service-clients-ext.md) y [Configuración de clientes en código](configuring-service-clients-code.md).

### Cerrar el cliente de servicio
<a name="using-closing-client"></a>

Como práctica recomendada, debe utilizar un cliente de servicio para varias llamadas al servicio de la API durante la vida útil de una aplicación. Sin embargo, si necesita un cliente de servicio para un solo uso o ya no lo necesita, ciérrelo.

Para liberar recursos, llame al método `close()` cuando el cliente de servicio deje de ser necesario.

```
ec2Client.close();
```

Si necesita un cliente de servicio para un solo uso, puede crear una instancia del cliente de servicio como un recurso en una instrucción `try`-with-resources. Los clientes de servicio implementan la interfaz de `[Autoclosable](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/AutoCloseable.html)`, por lo que el JDK llama automáticamente al método `close()` al final de la instrucción.

En el ejemplo siguiente, se muestra cómo utilizar un cliente de servicio para una llamada única. El `StsClient` que llama al AWS Security Token Service se cierra después de devolver el ID de la cuenta.

```
import software.amazon.awssdk.services.sts.StsClient;

String getAccountID() {
    try (StsClient stsClient = StsClient.create()) {
       return stsClient.getCallerIdentity().account();
    }
}
```

## Hacer solicitudes
<a name="using-making-requests"></a>

Utilice el cliente del servicio para realizar solicitudes al correspondiente Servicio de AWS.

Por ejemplo, este fragmento de código muestra cómo crear un objeto de `RunInstancesRequest` para crear una nueva instancia de Amazon EC2:

```
// Create the request by using the fluid setter methods of the request builder.
RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder()
        .imageId(amiId)
        .instanceType(InstanceType.T1_MICRO)
        .maxCount(1)
        .minCount(1)
        .build();

// Use the configured request with the service client.
RunInstancesResponse response = ec2Client.runInstances(runInstancesRequest);
```

En lugar de crear una solicitud y pasar la instancia, el SDK proporciona una API fluida que puede usar para crear una solicitud. Con la API fluida, puede usar expresiones lambda de Java para crear la solicitud “en línea”.

En el siguiente ejemplo, se reescribe el ejemplo anterior mediante la versión del `runInstances` [método que utiliza un creador](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#runInstances(java.util.function.Consumer)) para crear la solicitud.

```
// Create the request by using a lambda expression.
RunInstancesResponse response = ec2.runInstances(r -> r
                .imageId(amiId)
                .instanceType(InstanceType.T1_MICRO)
                .maxCount(1)
                .minCount(1));
```

### Uso de solicitudes para anular la configuración de clientes
<a name="using-override-client-config-request"></a>

Aunque un cliente de servicio es inmutable, puede anular muchos de sus ajustes en el nivel de solicitud. Al crear una solicitud, puede proporcionar una [AwsRequestOverrideConfiguration](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/AwsRequestOverrideConfiguration.html)instancia para proporcionar la configuración anulada. Algunos de los métodos que puede utilizar para anular la configuración del cliente son:
+ `apiCallAttemptTimeout`
+ `apiCallTimeout`
+ `credentialProvider`
+ `compressionConfiguration`
+ `putHeader`

Para ver un ejemplo de cómo anular la configuración de un cliente con una solicitud, supongamos que tiene el siguiente cliente de S3 con la configuración predeterminada.

```
S3Client s3Client = S3Client.create();
```

Desea descargar un archivo grande y asegurarse de que no se agote el tiempo de espera de la solicitud antes de que finalice la descarga. Para ello, aumente los valores de tiempo de espera de una sola solicitud `GetObject`, como se muestra en el código siguiente.

------
#### [ Standard API ]

```
AwsRequestOverrideConfiguration overrideConfiguration = AwsRequestOverrideConfiguration.builder()
    .apiCallTimeout(Duration.ofSeconds(100L))
    .apiCallAttemptTimeout(Duration.ofSeconds(25L))
    .build();

GetObjectRequest request = GetObjectRequest.builder()
    .bucket("amzn-s3-demo-bucket")
    .key("demo-key")
    .overrideConfiguration(overrideConfiguration)
    .build();

s3Client.getObject(request, myPath);
```

------
#### [ Fluent API ]

```
s3Client.getObject(b -> b
        .bucket("amzn-s3-demo-bucket")
        .key("demo-key")
        .overrideConfiguration(c -> c
            .apiCallTimeout(Duration.ofSeconds(100L))
            .apiCallAttemptTimeout(Duration.ofSeconds(25L))),
    myPath);
```

------

## Tratamiento de respuestas
<a name="using-handling-responses"></a>

El SDK devuelve un objeto de respuesta para la mayoría de las operaciones de servicio. El código puede procesar la información del objeto de respuesta en función de sus necesidades.

Por ejemplo, el siguiente fragmento de código imprime el primer identificador de instancia devuelto con el objeto [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesResponse.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/model/RunInstancesResponse.html) de la solicitud anterior.

```
RunInstancesResponse runInstancesResponse = ec2Client.runInstances(runInstancesRequest);
System.out.println(runInstancesResponse.instances().get(0).instanceId());
```

Sin embargo, no todas las operaciones devuelven un objeto de respuesta con datos específicos del servicio. En estas situaciones, puede consultar el estado de la respuesta HTTP para saber si la operación se realizó correctamente.

Por ejemplo, el código del siguiente fragmento comprueba la respuesta HTTP para ver si la operación [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sesv2/SesV2Client.html#deleteContactList(software.amazon.awssdk.services.sesv2.model.DeleteContactListRequest)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sesv2/SesV2Client.html#deleteContactList(software.amazon.awssdk.services.sesv2.model.DeleteContactListRequest)) de Amazon Simple Email Service se ha realizado correctamente. 

```
SesV2Client sesv2Client = SesV2Client.create();

DeleteContactListRequest request = DeleteContactListRequest.builder()
    .contactListName("ExampleContactListName")
    .build();

DeleteContactListResponse response = sesv2Client.deleteContactList(request);
if (response.sdkHttpResponse().isSuccessful()) {
    System.out.println("Contact list deleted successfully");
} else {
    System.out.println("Failed to delete contact list. Status code: " + response.sdkHttpResponse().statusCode());
}
```

# Programación asincrónica mediante AWS SDK for Java 2.x
<a name="asynchronous"></a>

El AWS SDK for Java 2.x incorpora clientes asincrónicos con compatibilidad de E/S no bloqueante que implementan un alto nivel de simultaneidad en algunos subprocesos. Sin embargo, no se garantiza una E/S no bloqueante total. Un cliente asincrónico puede realizar llamadas de bloqueo en algunos casos, como recuperación de credenciales, firma de solicitudes mediante [AWS Signature Version 4 (SigV4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) o detección de puntos de conexión. 

Los métodos síncronos bloquean la ejecución de los subprocesos hasta que el cliente recibe una respuesta del servicio. Los métodos asíncronos terminan de ejecutarse inmediatamente, devolviendo el control al subproceso que realiza la llamada sin esperar una respuesta.

Como un método asíncrono termina de ejecutarse antes de que haya una respuesta disponible, necesita una forma de obtener la respuesta cuando esté lista. Los métodos para cliente asíncrono en 2.x del AWS SDK para Java devuelven *objetos CompletableFuture* que le permiten acceder a la respuesta cuando esté lista.

## Uso de API de cliente asincrónicas
<a name="basics-async-non-streaming"></a>

Las firmas de los métodos de cliente asincrónicos son las mismas que las de los métodos sincrónicos, pero los métodos asincrónicos devuelven un objeto [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/CompletableFuture.html) que contiene los resultados de la operación asincrónica *en el futuro*. Si se produce un error mientras se ejecuta el método asincrónico del SDK, el error se lanza como `CompletionException`. 

Un método que se puede usar para obtener el resultado es encadenar un método `whenComplete()` al `CompletableFuture` devuelto por la llamada a métodos del SDK. El método `whenComplete()` recibe el resultado o un objeto del tipo Throwable de tipo `CompletionException` en función de cómo se haya completado la llamada asincrónica. Debe proporcionar una acción a `whenComplete()` para procesar o comprobar los resultados antes de que se devuelva al código de llamada.

Si quiere devolver algo distinto del objeto devuelto por el método del SDK, use el método `handle()` en su lugar. El método `handle()` utiliza los mismos parámetros que `whenComplete()`, pero se puede procesar el resultado y devolver un objeto.

Para esperar a que se complete la cadena asincrónica y recuperar los resultados de la finalización, puede llamar al método `join()`. Si el objeto `Throwable` no se administraba en la cadena, el método `join()` lanza un `CompletionException` no controlado que empaqueta la excepción original. Acceda a la excepción original con `CompletionException#getCause()`. También puede llamar al método `CompletableFuture#get()` para obtener los resultados de la finalización. Sin embargo, el método `get()` puede lanzar excepciones controladas.

El siguiente ejemplo muestra dos variantes de cómo se puede trabajar con el método `listTables()` del cliente asincrónico de DynamoDB. La acción pasada a `whenComplete()` registra simplemente una respuesta correcta, mientras que la versión `handle()` extrae la lista de nombres de tablas y la devuelve. En ambos casos, si se genera un error en la cadena asincrónica, el error se vuelve a lanzar para que el código del cliente pueda administrarlo.

 **Importaciones** 

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.ListTablesRequest;
import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;

import java.util.List;
import java.util.concurrent.CompletableFuture;
```

 **Código de** 

------
#### [ whenComplete() variation ]

```
public class DynamoDbAsyncListTables {

    public static void main(String[] args) {
        Region region = Region.US_EAST_1;
        DynamoDbAsyncClient dynamoDbAsyncClient = DynamoDbAsyncClient.builder().region(region).build();
        try {
            ListTablesResponse listTablesResponse = listTablesWhenComplete(dynamoDbAsyncClient).join();  // The join() method may throw a CompletionException.
            if (listTablesResponse.hasTableNames()){
                System.out.println("Table exist in this region: " + region.id());
            }
        } catch (RuntimeException e) {
            // Handle as needed. Here we simply print out the class names.
            System.out.println(e.getClass()); // Prints 'class java.util.concurrent.CompletionException'.
            System.out.println(e.getCause().getClass()); // Prints 'class software.amazon.awssdk.services.dynamodb.model.DynamoDbException'.
        }
    }

    public static CompletableFuture<ListTablesResponse> listTablesWhenComplete(DynamoDbAsyncClient client) {
        return client.listTables(ListTablesRequest.builder().build())
            .whenComplete((listTablesResponse, throwable) -> {
                if (listTablesResponse != null) {  // Consume the response.
                    System.out.println("The SDK's listTables method completed successfully.");
                } else {
                    RuntimeException cause = (RuntimeException) throwable.getCause(); // If an error was thrown during the SDK's listTables method it is wrapped in a CompletionException.
                                                                                      // The SDK throws only RuntimeExceptions, so this is a safe cast.
                    System.out.println(cause.getMessage());  // Log error here, but rethrow so the calling code can handle as needed.
                    throw cause;
                }
            });
    }
```

------
#### [ handle() variation ]

```
public class DynamoDbAsyncListTables {

    public static void main(String[] args) {
        Region region = Region.US_EAST_1;
        DynamoDbAsyncClient dynamoDbAsyncClient = DynamoDbAsyncClient.builder().region(region).build();
        try {
            List<String> tableNames = listTablesHandle(dynamoDbAsyncClient).join(); // The join() method may throw a CompletionException.
            tableNames.forEach(System.out::println);
        } catch (RuntimeException e) {
            // Handle as needed. Here we simply print out the class names.
            System.out.println(e.getClass()); // Prints 'class java.util.concurrent.CompletionException'.
            System.out.println(e.getCause().getClass()); // Prints 'class software.amazon.awssdk.services.dynamodb.model.DynamoDbException'.
        }
    }

    public static CompletableFuture<List<String>> listTablesHandle(DynamoDbAsyncClient client) {
        return client.listTables(ListTablesRequest.builder().build())
            .handle((listTablesResponse, throwable) -> {
                if (listTablesResponse != null) {
                    return listTablesResponse.tableNames(); // Return the list of table names.
                } else {
                    RuntimeException cause = (RuntimeException) throwable.getCause(); // If an error was thrown during the SDK's listTables method it is wrapped in a CompletionException.
                                                                                      // The SDK throws only RuntimeExceptions, so this is a safe cast.
                    System.out.println(cause.getMessage());  // Log error here, but rethrow so the calling code can handle as needed.
                    throw cause;
                }
            });
    }
}
```

------

## Administración de streaming en métodos asincrónicos
<a name="basics-async-streaming"></a>

Para métodos asincrónicos con contenido de streaming, debe proporcionar un objeto [AsyncRequestBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html) para proporcionar el contenido de forma incremental o un objeto [AsyncResponseTransformer](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncResponseTransformer.html) para recibir y procesar la respuesta.

El ejemplo siguiente carga un archivo en Amazon S3 de forma asincrónica utilizando la forma asincrónica de la operación `PutObject`.

 **Importaciones** 

```
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
```

 **Código de** 

```
/**
 * To run this AWS code example, ensure that you have setup your development environment, including your AWS credentials.
 *
 * For information, see this documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */

public class S3AsyncOps {

     public static void main(String[] args) {

         final String USAGE = "\n" +
                 "Usage:\n" +
                 "    S3AsyncOps <bucketName> <key> <path>\n\n" +
                 "Where:\n" +
                 "    bucketName - the name of the Amazon S3 bucket (for example, bucket1). \n\n" +
                 "    key - the name of the object (for example, book.pdf). \n" +
                 "    path - the local path to the file (for example, C:/AWS/book.pdf). \n" ;

        if (args.length != 3) {
            System.out.println(USAGE);
             System.exit(1);
        }

        String bucketName = args[0];
        String key = args[1];
        String path = args[2];

        Region region = Region.US_WEST_2;
        S3AsyncClient client = S3AsyncClient.builder()
                .region(region)
                .build();

        PutObjectRequest objectRequest = PutObjectRequest.builder()
                .bucket(bucketName)
                .key(key)
                .build();

        // Put the object into the bucket
        CompletableFuture<PutObjectResponse> future = client.putObject(objectRequest,
                AsyncRequestBody.fromFile(Paths.get(path))
        );
        future.whenComplete((resp, err) -> {
            try {
                if (resp != null) {
                    System.out.println("Object uploaded. Details: " + resp);
                } else {
                    // Handle error
                    err.printStackTrace();
                }
            } finally {
                // Only close the client when you are completely done with it
                client.close();
            }
        });

        future.join();
    }
}
```

En el ejemplo siguiente se obtiene un archivo de Amazon S3 utilizando la forma asincrónica de la operación `GetObject`.

 **Importaciones** 

```
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;
```

 **Código de** 

```
/**
 * To run this AWS code example, ensure that you have setup your development environment, including your AWS credentials.
 *
 * For information, see this documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 */

public class S3AsyncStreamOps {

    public static void main(String[] args) {

        final String USAGE = "\n" +
                "Usage:\n" +
                "    S3AsyncStreamOps <bucketName> <objectKey> <path>\n\n" +
                "Where:\n" +
                "    bucketName - the name of the Amazon S3 bucket (for example, bucket1). \n\n" +
                "    objectKey - the name of the object (for example, book.pdf). \n" +
                "    path - the local path to the file (for example, C:/AWS/book.pdf). \n" ;

        if (args.length != 3) {
            System.out.println(USAGE);
            System.exit(1);
         }

        String bucketName = args[0];
        String objectKey = args[1];
        String path = args[2];

        Region region = Region.US_WEST_2;
        S3AsyncClient client = S3AsyncClient.builder()
                .region(region)
                .build();

        GetObjectRequest objectRequest = GetObjectRequest.builder()
                .bucket(bucketName)
                .key(objectKey)
                .build();

        CompletableFuture<GetObjectResponse> futureGet = client.getObject(objectRequest,
                AsyncResponseTransformer.toFile(Paths.get(path)));

        futureGet.whenComplete((resp, err) -> {
            try {
                if (resp != null) {
                    System.out.println("Object downloaded. Details: "+resp);
                } else {
                    err.printStackTrace();
                }
            } finally {
               // Only close the client when you are completely done with it
                client.close();
            }
        });
        futureGet.join();
    }
}
```

## Configuración de opciones asincrónicas avanzadas
<a name="advanced-operations"></a>

El AWS SDK para Java 2.x usa [Netty](https://netty.io), una plataforma de aplicación de red asíncrona y basado en eventos, para gestionar subprocesos de E/S. El AWS SDK para Java 2.x crea un `ExecutorService` después de Netty para completar los futuros devueltos desde la solicitud del cliente HTTP al cliente Netty. Esta abstracción reduce el riesgo de que una aplicación interrumpa el proceso de sincronización si los desarrolladores deciden detener o suspender los subprocesos. De forma predeterminada, cada cliente asíncrono crea un grupo de subprocesos en función del número de procesadores y gestiona las tareas de una cola dentro del `ExecutorService`.

Puede especificar una implementación de JDK específica de `ExecutorService` cuando cree su cliente asincrónico. El siguiente fragmento crea un `ExecutorService` con un número fijo de subprocesos.

 **Código de** 

```
S3AsyncClient clientThread = S3AsyncClient.builder()
  .asyncConfiguration(
    b -> b.advancedOption(SdkAdvancedAsyncClientOption
      .FUTURE_COMPLETION_EXECUTOR,
      Executors.newFixedThreadPool(10)
    )
  )
  .build();
```

Para optimizar el rendimiento, puede administrar su propio ejecutor de grupo de subprocesos e incluirlo al configurar el cliente.

```
ThreadPoolExecutor executor = new ThreadPoolExecutor(50, 50,
    10, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(<custom_value>),
    new ThreadFactoryBuilder()
      .threadNamePrefix("sdk-async-response").build());

// Allow idle core threads to time out
executor.allowCoreThreadTimeOut(true);

S3AsyncClient clientThread = S3AsyncClient.builder()
  .asyncConfiguration(
    b -> b.advancedOption(SdkAdvancedAsyncClientOption
      .FUTURE_COMPLETION_EXECUTOR,
      executor
    )
  )
  .build();
```

# Mejores prácticas para usar el AWS SDK for Java 2.x
<a name="best-practices"></a>

## Prevención del bloqueo de solicitudes configurando tiempos de espera de la API
<a name="bestpractice5"></a>

El SDK proporciona [valores predeterminados](https://github.com/aws/aws-sdk-java-v2/blob/a0c8a0af1fa572b16b5bd78f310594d642324156/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java#L134) para algunas opciones de tiempo de espera, como el tiempo de espera de la conexión y los tiempos de espera del socket, pero no para los tiempos de espera de las llamadas a la API ni para los tiempos de espera de los intentos de llamadas individuales a la API. Se recomienda establecer tiempos de espera tanto para los intentos individuales como para toda la solicitud. Esto garantizará que la aplicación pueda responder rápido a los errores y de forma óptima cuando se produzcan problemas transitorios que puedan provocar que los intentos de solicitud tarden más en completarse o surjan problemas graves de red.

Puede configurar los tiempos de espera para todas las solicitudes realizadas por los clientes de un servicio mediante `[ClientOverrideConfiguration\$1apiCallAttemptTimeout](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html#apiCallAttemptTimeout())` y `[ClientOverrideConfiguration\$1apiCallTimeout](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html#apiCallTimeout())`.

En el siguiente ejemplo, se muestra la configuración de un cliente Amazon S3 con valores de tiempo de espera personalizados.

```
S3Client.builder()
        .overrideConfiguration(
             b -> b.apiCallTimeout(Duration.ofSeconds(<custom value>))
                   .apiCallAttemptTimeout(Duration.ofMillis(<custom value>)))
        .build();
```

**`apiCallAttemptTimeout`**  
Esta configuración establece la cantidad de tiempo para un único intento HTTP, tras el cual se puede volver a intentar la llamada a la API.

**`apiCallTimeout`**  
El valor de esta propiedad configura la cantidad de tiempo de toda la ejecución, incluidos todos los reintentos.

Como alternativa a establecer estos valores de tiempo de espera en el cliente de servicio, puede usar [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/RequestOverrideConfiguration.html#apiCallTimeout()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/RequestOverrideConfiguration.html#apiCallTimeout()) y `[RequestOverrideConfiguration\$1apiCallAttemptTimeout()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/RequestOverrideConfiguration.html#apiCallAttemptTimeout())` para configurar una sola solicitud.

El ejemplo siguiente configura una única solicitud de `listBuckets` con valores de tiempo de espera personalizados.

```
s3Client.listBuckets(lbr -> lbr.overrideConfiguration(
        b -> b.apiCallTimeout(Duration.ofSeconds(<custom value>))
               .apiCallAttemptTimeout(Duration.ofMillis(<custom value>))));
```

Al utilizar juntas estas propiedades, establece un límite estricto en el tiempo total dedicado a todos los intentos entre reintentos. También configura una solicitud HTTP individual para poder responder rápido a los errores en las solicitudes lentas.

## Mejora del rendimiento reutilizando clientes de servicio
<a name="bestpractice1"></a>

Cada [cliente de servicio](work-witih-clients.md) mantiene su propio grupo de conexiones HTTP. Una conexión que ya existe en el grupo se puede reutilizar mediante una nueva solicitud para reducir el tiempo necesario para establecer una nueva conexión. Recomendamos compartir una sola instancia del cliente para evitar la sobrecarga que supone tener demasiados grupos de conexiones que no se utilizan de forma eficaz. Todos los clientes de servicio son seguros para subprocesos.

Si no quiere compartir una instancia de cliente, utilice `close()` en la instancia para liberar los recursos cuando el cliente no sea necesario.

## Prevención de pérdidas de recursos cerrando los clientes de servicio no utilizados
<a name="bestpractice-close-client"></a>

Cierre de un [cliente de servicio](work-witih-clients.md) para liberar recursos, como subprocesos, si ya no es necesario. Si no quiere compartir una instancia de cliente, utilice `close()` en la instancia para liberar los recursos cuando el cliente no sea necesario.

## Prevención del agotamiento de grupos de conexiones cerrando flujos de entrada
<a name="bestpractice2"></a>

Para operaciones de secuencia, como `[S3Client\$1getObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#getObject(java.util.function.Consumer,java.nio.file.Path))`, si trabaja directamente con `[ResponseInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/ResponseInputStream.html)`, recomendamos que haga lo siguiente:
+ Lea todos los datos de la secuencia de entrada lo antes posible.
+ Cierre la secuencia de entrada cuanto antes.

Hacemos estas recomendaciones porque la secuencia de entrada es un flujo directo de datos de la conexión HTTP y la conexión HTTP subyacente no se puede reutilizar hasta que se hayan leído todos los datos de la secuencia y esta se cierre. Si no se siguen estas reglas, el cliente puede quedarse sin recursos por asignar demasiadas conexiones HTTP abiertas pero no utilizadas.

## Optimización del rendimiento de HTTP para la carga de trabajo de la aplicación
<a name="bestpractice3"></a>

El SDK proporciona un conjunto de [configuraciones http predeterminadas](https://github.com/aws/aws-sdk-java-v2/blob/master/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java) que se aplican a los casos de uso generales. Recomendamos a los clientes que definan las configuraciones HTTP de sus aplicaciones en función de sus casos de uso. 

Como buen punto de partida, el SDK ofrece una característica de [configuración inteligente de valores predeterminados.](http-configuration.md#http-config-smart-defaults) Esta característica está disponible a partir de la versión 2.17.102. Debe seleccionar un modo según su uso, lo que proporciona valores de configuración razonables. 

## Mejora del rendimiento de SSL con OpenSSL para clientes asincrónicos
<a name="bestpractice4"></a>

De forma predeterminada, el [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html) de SDK utiliza la implementación SSL predeterminada del JDK como `SslProvider`. Nuestras pruebas revelaron que OpenSSL funciona mejor que la implementación predeterminada de JDK. La comunidad de Netty también [recomienda usar OpenSSL](https://netty.io/wiki/requirements-for-4.x.html#tls-with-openssl). 

Para usar OpenSSL, agregue `netty-tcnative` a sus dependencias. Para obtener detalles de configuración, consulte la [documentación del proyecto Netty](https://netty.io/wiki/forked-tomcat-native.html).

Una vez que haya configurado su proyecto con `netty-tcnative`, la instancia del `NettyNioAsyncHttpClient` seleccionará OpenSSL automáticamente. Como alternativa, puede configurar el `SslProvider` de forma explícita mediante el compilador de `NettyNioAsyncHttpClient`, como muestra el siguiente fragmento.

```
NettyNioAsyncHttpClient.builder()
                        .sslProvider(SslProvider.OPENSSL)
                        .build();
```

## Monitorización del rendimiento de las aplicaciones con métricas del SDK
<a name="bestpractice6"></a>

El SDK para Java puede [recopilar métricas](metrics.md) para los clientes de servicio de su aplicación. Puede utilizar estas métricas para identificar problemas de rendimiento, revisar las tendencias generales de uso, revisar las excepciones de clientes de servicio devueltas o profundizar para comprender un problema concreto.

Le recomendamos que recopile métricas y, a continuación, analice los Amazon CloudWatch Logs para comprender mejor el rendimiento de su aplicación.

# Manejo de errores en el AWS SDK for Java 2.x
<a name="handling-exceptions"></a>

Comprender cómo y cuándo se producen AWS SDK for Java 2.x excepciones es importante para crear aplicaciones de alta calidad con el SDK. En las siguientes secciones se describen los diferentes casos de excepciones que produce el SDK y cómo tratarlas correctamente.

## ¿Por qué excepciones no controladas?
<a name="why-unchecked-exceptions"></a>

 AWS SDK para Java Utiliza excepciones en tiempo de ejecución (o no comprobadas) en lugar de excepciones comprobadas por los siguientes motivos:
+ Para permitir a los desarrolladores un control minucioso de los errores que desean administrar sin obligarles a abordar casos excepcionales que no les preocupan (o que les obligan a detallar su código en exceso)
+ Para evitar problemas de escalabilidad inherentes a las excepciones controladas en aplicaciones grandes

En general, las excepciones controladas funcionan bien a pequeña escala, pero pueden ser problemáticas cuando las aplicaciones crecen y se vuelven más complejas.

## AwsServiceException (y subclases)
<a name="sdkserviceexception-and-subclasses"></a>

 [AwsServiceException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsServiceException.html)es la excepción más común que experimentará al AWS SDK para Java usar. `AwsServiceException`es una subclase de las más generales [SdkServiceException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html). `AwsServiceException`s representan una respuesta de error de un Servicio de AWS. Por ejemplo, si intentas terminar una Amazon EC2 instancia que no existe, Amazon EC2 devolverá una respuesta de error y todos los detalles de esa respuesta de error se incluirán en la `AwsServiceException` que se arroje. 

Cuando encuentres una`AwsServiceException`, sabrás que tu solicitud se envió correctamente, Servicio de AWS pero que no se pudo procesar correctamente. Esto puede ser debido a errores en los parámetros de la solicitud o a problemas en el servicio.

 `AwsServiceException` proporciona información como:
+ Código de estado HTTP devuelto
+ Código AWS de error devuelto
+ Mensaje de error detallado del servicio de la [AwsErrorDetails](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsErrorDetails.html)clase
+  AWS ID de solicitud de la solicitud fallida

En algunos casos, se produce una subclase de `AwsServiceException` para permitir a los desarrolladores un control minucioso del tratamiento de casos de error a través de bloques de captura. La referencia de la API del SDK de Java [AwsServiceException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsServiceException.html)muestra la gran cantidad de `AwsServiceException` subclases. Utilice los enlaces de las subclases para profundizar y ver las excepciones granulares generadas por un servicio.

Por ejemplo, los siguientes enlaces a la referencia API del SDK muestran las jerarquías de excepciones para algunos Servicios de AWS comunes. La lista de subclases que se muestra en cada página muestra las excepciones específicas que su código puede capturar.
+ [Amazon S3](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/S3Exception.html)
+ [DynamoDB](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/model/DynamoDbException.html)
+ [Amazon SQS](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sqs/model/SqsException.html)

Para obtener más información sobre una excepción, inspeccione `errorCode` el [AwsErrorDetails](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsErrorDetails.html)objeto. Puede usar el valor `errorCode` para buscar información en la API de la guía de servicios. Por ejemplo, si se captura un `S3Exception` y el valor `AwsErrorDetails#errorCode()` es `InvalidRequest`, utilice la [lista de códigos de error](https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList) de la Referencia de la API de Amazon S3 para ver más detalles.

## SdkClientException
<a name="sdkclientexception"></a>

 [SdkClientException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkClientException.html)indica que se ha producido un problema en el código del cliente de Java, ya sea al intentar enviar una solicitud AWS o al analizar una respuesta desde él AWS. Un `SdkClientException` es generalmente más grave que uno e indica un problema importante que impide que el cliente realice llamadas de servicio a AWS los servicios. `SdkServiceException` Por ejemplo, `SdkClientException` si no hay ninguna conexión de red disponible cuando se intenta llamar a una operación en uno de los clientes. AWS SDK para Java 

## Excepciones y comportamiento de reintentos
<a name="retried-exceptions"></a>

El SDK para Java vuelve a intentar las solicitudes de varias [excepciones del lado del cliente](https://github.com/aws/aws-sdk-java-v2/blob/13985e0668a9a0b12ad331644e3c4fd1385c2cd7/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/retry/SdkDefaultRetrySetting.java#L79C41-L79C41) y de los [códigos de estado HTTP](https://github.com/aws/aws-sdk-java-v2/blob/13985e0668a9a0b12ad331644e3c4fd1385c2cd7/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/retry/SdkDefaultRetrySetting.java#L72C31-L72C31) que recibe de las respuestas. Servicio de AWS Estos errores se gestionan como parte del `RetryMode` heredado que los clientes de servicios utilizan de forma predeterminada. La referencia de la API de Java para `[RetryMode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/RetryMode.html)` describe las distintas formas de configurar el modo.

Para personalizar las excepciones y los códigos de estado HTTP que activan los reintentos automáticos, configure su cliente de servicio con una `[RetryPolicy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/RetryPolicy.html)` que añada instancias `[RetryOnExceptionsCondition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/RetryOnExceptionsCondition.html)` y `[RetryOnStatusCodeCondition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/retry/conditions/RetryOnErrorCodeCondition.html)`.

# Uso de resultados paginados en la versión 2.x AWS SDK para Java
<a name="pagination"></a>

Muchas AWS operaciones devuelven resultados paginados cuando el objeto de respuesta es demasiado grande para mostrarlos en una sola respuesta. En la AWS SDK para 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 para 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](using.md), y ha configurado su entorno con [acceso de inicio de sesión único](get-started-auth.md#setup-credentials).

## Paginación síncrona
<a name="synchronous-pagination"></a>

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
<a name="iterate-pages"></a>

El primer ejemplo demuestra el uso de un objeto paginador de `listRes`, una instancia de [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/paginators/ListObjectsV2Iterable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/paginators/ListObjectsV2Iterable.html), para iterar por 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](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/S3Object.html)` 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.

#### Importaciones
<a name="synchronous-pagination-ex-import"></a>

```
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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L112) en GitHub.

### Iterar sobre objetos
<a name="iterate-objects"></a>

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 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/pagination/sync/SdkIterable.html) que proporciona varios métodos para procesar los elementos de contenido subyacentes.

#### Usar un stream
<a name="use-a-stream"></a>

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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L127) en GitHub.

#### Usar un buble for-each
<a name="for-loop"></a>

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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L133) en GitHub.

### Paginación manual
<a name="manual-pagination"></a>

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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L90) en GitHub.

## Paginación asíncrona
<a name="asynchronous-pagination"></a>

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
<a name="iterate-pages-async"></a>

Los dos ejemplos siguientes utilizan un cliente de DynamoDB asincrónico que llama al método `listTablesPaginator` con una solicitud para obtener un [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/paginators/ListTablesPublisher.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/dynamodb/paginators/ListTablesPublisher.html). `ListTablesPublisher` implementa dos interfaces, que ofrecen muchas opciones para procesar respuestas. Analizaremos los métodos de cada interfaz.

#### Utilizar un `Subscriber`.
<a name="use-a-subscriber"></a>

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 transmisiones reactivas, consulte el repositorio de transmisiones reactivas. GitHub ](https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.2/README.md)

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

##### Importaciones
<a name="use-a-subscriber-ex-imports"></a>

```
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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L83) en. GitHub

#### Utilizar un `Consumer`.
<a name="id1pagination"></a>

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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L96) en GitHub.

### Recorrer en iteración nombres de tablas
<a name="iterate-objects-async"></a>

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 [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/SdkPublisher.html) que se puede usar para solicitar elementos en todas las páginas.

#### Utilizar un `Subscriber`.
<a name="id2"></a>

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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L147) en GitHub.

#### Utilizar un `Consumer`.
<a name="for-loop-async"></a>

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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L161) en GitHub.

### Usar una biblioteca de terceros
<a name="use-third-party-library"></a>

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 en GitHub](https://github.com/ReactiveX/RxJava/wiki) 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](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L198) en GitHub.

# Utilizando camareros en el AWS SDK for Java 2.x
<a name="waiters"></a>

La utilidad waiters de la versión AWS SDK para Java 2.x permite validar que AWS los recursos se encuentran en un estado específico antes de realizar operaciones con esos recursos.

Un *camarero* es una abstracción que se utiliza para sondear AWS recursos, como DynamoDB tablas o Amazon S3 cubos, hasta que se alcance el estado deseado (o hasta que se determine que el recurso nunca alcanzará el estado deseado). En lugar de escribir una lógica para sondear continuamente AWS los recursos, lo que puede resultar engorroso y propenso a errores, puede utilizar waiters para sondear un recurso y hacer que el código siga ejecutándose una vez que el recurso esté listo.

## Requisitos previos
<a name="prerequisiteswaiters"></a>

[Para poder usar camareros en un proyecto con el AWS SDK para Java, debes completar los pasos de Configuración de la versión 2.x. AWS SDK para Java](setup.md)

También debe configurar las dependencias de su proyecto (por ejemplo, en su archivo `pom.xml` o `build.gradle`) para usar la versión `2.15.0` o posterior del AWS SDK para Java.

Por ejemplo:

```
<project>
  <dependencyManagement>
   <dependencies>
      <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>bom</artifactId>
        <version>2.27.21</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
   </dependencies>
  </dependencyManagement>
</project>
```

## Uso de esperadores
<a name="id1waiters"></a>

Para crear una instancia de un objeto esperador, cree antes un cliente de servicio. Establece el método del cliente `waiter()` de servicio como el valor del objeto esperador. Una vez que exista la instancia de esperador, configure sus opciones de respuesta para ejecutar el código apropiado.

### Programación asíncrona
<a name="synchronous-programming"></a>

**El siguiente fragmento de código muestra cómo esperar a que una DynamoDB mesa exista y esté en estado ACTIVO.**

```
DynamoDbClient dynamo = DynamoDbClient.create();
DynamoDbWaiter waiter = dynamo.waiter();

WaiterResponse<DescribeTableResponse> waiterResponse =
  waiter.waitUntilTableExists(r -> r.tableName("myTable"));

// print out the matched response with a tableStatus of ACTIVE
waiterResponse.matched().response().ifPresent(System.out::println);
```

### Programación asíncrona
<a name="asynchronous-programming"></a>

El siguiente fragmento de código muestra cómo esperar a que una DynamoDB tabla deje de existir.

```
DynamoDbAsyncClient asyncDynamo = DynamoDbAsyncClient.create();
DynamoDbAsyncWaiter asyncWaiter = asyncDynamo.waiter();

CompletableFuture<WaiterResponse<DescribeTableResponse>> waiterResponse =
          asyncWaiter.waitUntilTableNotExists(r -> r.tableName("myTable"));

waiterResponse.whenComplete((r, t) -> {
  if (t == null) {
   // print out the matched ResourceNotFoundException
   r.matched().exception().ifPresent(System.out::println);
  }
}).join();
```

## Configurar los esperadores
<a name="configuring-waiters"></a>

Puede personalizar la configuración de un esperador utilizando el `overrideConfiguration()` en su creador. Para algunas operaciones, puede aplicar una configuración personalizada al realizar la solicitud.

### Configurar un esperador
<a name="configure-a-waiter"></a>

En el siguiente fragmento de código se muestra cómo anular la configuración de un esperador.

```
// sync
DynamoDbWaiter waiter =
   DynamoDbWaiter.builder()
          .overrideConfiguration(b -> b.maxAttempts(10))
          .client(dynamoDbClient)
          .build();
// async
DynamoDbAsyncWaiter asyncWaiter =
   DynamoDbAsyncWaiter.builder()
          .client(dynamoDbAsyncClient)
          .overrideConfiguration(o -> o.backoffStrategy(
               FixedDelayBackoffStrategy.create(Duration.ofSeconds(2))))
          .scheduledExecutorService(Executors.newScheduledThreadPool(3))
          .build();
```

### Anular la configuración de una solicitud específica
<a name="override-configuration-for-a-specific-request"></a>

El siguiente fragmento de código muestra cómo anular la configuración de un esperador en función de cada solicitud. Tenga en cuenta que solo algunas operaciones tienen configuraciones personalizables.

```
waiter.waitUntilTableNotExists(b -> b.tableName("myTable"),
               o -> o.maxAttempts(10));

asyncWaiter.waitUntilTableExists(b -> b.tableName("myTable"),
                 o -> o.waitTimeout(Duration.ofMinutes(1)));
```

## Ejemplos de código
<a name="code-examples"></a>

Para ver un ejemplo completo del uso de waiters with DynamoDB, consulta [CreateTable.java](https://github.com/awsdocs/aws-doc-sdk-examples/blob/869b7ddbc7c8f66c7c45acd5b813429aff37003e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTable.java) en el AWS repositorio de ejemplos de código.

Para ver un ejemplo completo del uso de waiters with Amazon S3, consulta [S3 BucketOps .java](https://github.com/awsdocs/aws-doc-sdk-examples/blob/869b7ddbc7c8f66c7c45acd5b813429aff37003e/javav2/example_code/s3/src/main/java/com/example/s3/S3BucketOps.java) en el AWS repositorio de ejemplos de código.

# Solución de problemas FAQs
<a name="troubleshooting"></a>

A medida que lo utilice AWS SDK for Java 2.x en sus aplicaciones, es posible que se produzcan los errores de tiempo de ejecución que se enumeran en este tema. Utilice estas sugerencias como ayuda para descubrir la causa principal y resolver el error.

## ¿Cómo puedo corregir el error “`java.net.SocketException`: Connection reset” o “server failed to complete the response”?
<a name="faq-socketexception"></a>

Un error al restablecer la conexión indica que el anfitrión Servicio de AWS, el servidor o cualquier intermediario (por ejemplo, una puerta de enlace NAT, un proxy o un equilibrador de carga) cerró la conexión antes de que se completara la solicitud. Dado que las causas pueden ser múltiples, es necesario saber por qué se cierra la conexión para encontrar una solución. Los siguientes elementos suelen provocar el cierre de una conexión.
+ **La conexión está inactiva.**Esto es habitual en las operaciones de streaming, en las que los datos no se escriben ni salen de la red durante un período de tiempo, por lo que un intermediario detecta que la conexión está interrumpida y la cierra. Para evitarlo, asegúrate de que tu aplicación descargue o cargue datos de forma activa.
+ **Usted ha cerrado el cliente de HTTP o el SDK.** Asegúrese de no cerrar recursos mientras estén en uso.
+ **Un proxy configurado incorrectamente.** Intente omitir los proxies que haya configurado para comprobar si se soluciona el problema. Si se soluciona el problema, el proxy está cerrando la conexión por alguna razón. Investigue su proxy específico para determinar por qué cierra la conexión.

Si no puede identificar el problema, ejecute un volcado de TCP para una conexión afectada en la periferia del cliente de la red (por ejemplo, después de cualquier servidor proxy que usted controle). 

Si ves que el AWS punto final está enviando un `TCP RST` (restablecimiento), [ponte en contacto con el servicio afectado](https://aws.amazon.com/contact-us/) para ver si pueden determinar el motivo del restablecimiento. Prepárate para proporcionar una solicitud IDs y marcar la hora en la que se produjo el problema. El equipo de AWS soporte también podría beneficiarse de [los registros de cables](logging-slf4j.md#sdk-java-logging-verbose) que muestren exactamente qué bytes envía y recibe su aplicación y cuándo.

## ¿Cómo puedo corregir “tiempo de espera de conexión”?
<a name="faq-connection-timeout"></a>

Un error en el tiempo de espera de la conexión indica que el anfitrión Servicio de AWS, el servidor o cualquier intermediario (por ejemplo, una puerta de enlace NAT, un proxy o un equilibrador de carga) no pudieron establecer una nueva conexión con el servidor dentro del tiempo de espera de conexión configurado. Los siguientes elementos describen causas comunes de este problema.
+ **El tiempo de espera de conexión configurado es demasiado bajo.** De forma predeterminada, el tiempo de espera de conexión es de 2 segundos en AWS SDK for Java 2.x. Si establece el tiempo de espera de conexión demasiado bajo, es posible que aparezca este error. El tiempo de espera de conexión recomendado es de 1 segundo si solo hace llamadas dentro de una región y de 3 segundos si realiza solicitudes entre regiones.
+ **Un proxy configurado incorrectamente.** Intente omitir los proxies que haya configurado para comprobar si se soluciona el problema. Si se soluciona, la razón del problema del tiempo de espera de conexión se encuentra en el proxy. Investigue su proxy específico para determinar la causa

Si no puede identificar el problema, ejecute un volcado de TCP para una conexión afectada en la periferia del cliente de la red (por ejemplo, después de cualquier servidor proxy que usted controle) para investigar posibles problemas de red.

## ¿Cómo puedo corregir “`java.net.SocketTimeoutException`: Read timed out”?
<a name="faq-socket-timeout"></a>

Un error de tiempo de espera agotado de lectura indica que la JVM ha intentado leer los datos del sistema operativo subyacente, pero no se devolvieron dentro del tiempo configurado mediante el SDK. Este error puede producirse si el sistema operativo Servicio de AWS, el operador o cualquier intermediario (por ejemplo, una puerta de enlace NAT, un proxy o un equilibrador de carga) no envía los datos en el tiempo esperado por la JVM. Dado que las causas pueden ser múltiples, es necesario saber por qué no se devuelven los datos para encontrar una solución.

Ejecute un volcado de TCP para una conexión afectada en la periferia del cliente de la red (por ejemplo, después de cualquier servidor proxy que usted controle). 

Si ve que el AWS punto final está enviando un `TCP RST` (restablecimiento), [póngase en contacto con el servicio afectado](https://aws.amazon.com/contact-us/). Prepárate para proporcionar una solicitud IDs y marcar la hora en la que se produjo el problema. El equipo de AWS soporte también podría beneficiarse de [los registros de cables](logging-slf4j.md#sdk-java-logging-verbose) que muestren exactamente qué bytes envía y recibe su aplicación y cuándo.

## ¿Cómo puedo corregir el error “Unable to execute HTTP request: Timeout waiting for connection from pool”?
<a name="faq-pool-timeout"></a>

Este error indica que una solicitud no puede obtener una conexión del grupo en el plazo de tiempo máximo especificado. Para solucionar el problema, te recomendamos que [habilites las métricas del lado del cliente del SDK para publicar las métricas](metrics.md) en Amazon. CloudWatch Las métricas de HTTP pueden ayudar a reducir el problema raíz. Los siguientes elementos describen causas comunes de este error.
+ **Filtración de conexión.** Puede investigar esto comprobando las métricas de `LeasedConcurrency`, `AvailableConcurrency` y `MaxConcurrency`. Si `LeasedConcurrency` aumenta hasta alcanzar `MaxConcurrency` pero no disminuye, es posible que haya una filtración de conexión. Una causa común de filtración es que haya una operación de streaming, como un método `getObject` de S3, que no se ha cerrado. Recomendamos que la aplicación lea todos los datos del flujo de entrada lo antes posible y [cierre el flujo de entrada después](best-practices.md#bestpractice2). En el siguiente gráfico se muestra el aspecto que podrían tener las métricas del SDK en caso de filtración de conexión.  
![\[Captura de pantalla de CloudWatch las métricas que muestran una posible pérdida de conexión.\]](http://docs.aws.amazon.com/es_es/sdk-for-java/latest/developer-guide/images/JavaDevGuide-connection-leak-metrics-chart.png)
+ **Falta de grupos de conexiones.**Esta situación puede producirse si la tasa de solicitudes es demasiado alta y el tamaño del grupo de conexiones que se ha configurado no puede satisfacer la demanda de las solicitudes. El tamaño predeterminado del grupo de conexiones es 50 y, cuando las conexiones del grupo alcanzan el máximo, el cliente de HTTP pone en cola las solicitudes entrantes hasta que haya conexiones disponibles. En el siguiente gráfico se muestra el aspecto que podrían tener las métricas del SDK en caso de falta de grupos de conexiones.  
![\[Captura de pantalla de CloudWatch las métricas que muestran cómo podría ser la falta de conexiones por falta de conexiones.\]](http://docs.aws.amazon.com/es_es/sdk-for-java/latest/developer-guide/images/JavaDevGuide-connection-pool-starvation-chart.png)

  Para mitigar este problema, considere la posibilidad de tomar alguna de estas medidas.
  + Aumente el tamaño del grupo de conexiones.
  + Aumente el tiempo de espera de adquisición.
  + Disminuya la tasa de solicitudes.

  Al aumentar el número máximo de conexiones, el rendimiento del cliente puede aumentar (a menos que la interfaz de red ya esté plenamente utilizada). Sin embargo, con el tiempo es posible que se produzcan limitaciones del sistema operativo en cuanto al número de descriptores de archivos utilizados por el proceso. Si ya utiliza plenamente la interfaz de red o no puede aumentar más el número de conexiones, pruebe a aumentar el tiempo de espera de adquisición. Con este aumento se gana tiempo adicional para las solicitudes de adquisición de una conexión antes de que se agote el tiempo de espera. Si las conexiones no se liberan, se agotará el tiempo de espera de las solicitudes subsiguientes. 

  Si no puede corregir el problema utilizando las dos primeras medidas, reduzca la tasa de solicitudes probando las siguientes opciones.
  + Simplifique las solicitudes para que las grandes ampliaciones de tráfico no sobrecarguen al cliente.
  + Sea más eficiente con las llamadas a Servicios de AWS.
  + Aumente el número de hosts que envían solicitudes.
+ **Los subprocesos de E/S están demasiado ocupados.** Esto solo se aplica si utiliza un cliente de SDK asincrónico con [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.html). Si la `AvailableConcurrency` métrica no es baja (lo que indica que hay conexiones disponibles en el grupo), pero `ConcurrencyAcquireDuration` es alta, podría deberse a que los I/O subprocesos no pueden gestionar las solicitudes. Asegúrese de no hacerse pasar por `Runnable:run` un [ejecutor de future complete](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.html#FUTURE_COMPLETION_EXECUTOR) y de realizar una tarea que requiera mucho tiempo en la cadena de finalización futura de la respuesta, ya que esto puede bloquear un I/O hilo. Si ese no es el caso, considere la posibilidad de aumentar el número de I/O subprocesos mediante el `[eventLoopGroupBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClient.Builder.html#eventLoopGroupBuilder(software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup.Builder))` método. Como referencia, la cantidad predeterminada de subprocesos de E/S para una instancia de `NettyNioAsyncHttpClient` es el doble del número de núcleos de CPU del host.
+ **Alta latencia de establecimiento de comunicación de TLS.** Si la métrica `AvailableConcurrency` está cerca de 0 y `LeasedConcurrency` es inferior a `MaxConcurrency`, puede deberse a que sea alta la latencia de establecimiento de comunicación de TLS. En el siguiente gráfico se muestra el aspecto que podrían tener las métricas del SDK en caso de latencia alta del establecimiento de comunicación de TLS.  
![\[Captura de pantalla de CloudWatch las métricas que podrían indicar una latencia alta del protocolo de enlace de TLS.\]](http://docs.aws.amazon.com/es_es/sdk-for-java/latest/developer-guide/images/JavaDevGuide-high-tls-latency-chart.png)

  En el caso de los clientes HTTP que ofrece el SDK de Java y que no están basados en CRT, pruebe a habilitar los [registros de TLS](security-java-tls.md) para solucionar problemas de TLS. Para el cliente de HTTP basado en AWS CRT, pruebe a habilitar [registros de AWS CRT](logging-slf4j.md#sdk-java-logging-verbose). Si observas que el AWS punto final tarda mucho en realizar un protocolo de enlace TLS, ponte en [contacto con](https://aws.amazon.com/contact-us/) el servicio afectado.

## ¿Cómo puedo corregir `NoClassDefFoundError`, `NoSuchMethodError` o `NoSuchFieldError`?
<a name="faq-classpath-errors"></a>

Un `NoClassDefFoundError` indica que no se ha podido cargar una clase en tiempo de ejecución. Estas son las dos causas más comunes de este error:
+ la clase no existe en la ruta de clases porque falta el JAR o porque hay una versión incorrecta del JAR en la ruta de clases.
+ la clase no se ha podido cargar porque su inicializador estático ha lanzado una excepción.

Del mismo modo, `NoSuchMethodError` y `NoSuchFieldError` suelen deberse a una versión de JAR que no coincide. Le recomendamos que siga estos siguientes pasos:

1. **Compruebe sus dependencias** para asegurarse de que está usando la *misma versión de todos los jar del SDK*. Cuando no se encuentra una clase, un método o un campo lo más común es que se deba a que ha actualizado a una nueva versión del cliente pero sigue usando una versión antigua de dependencia “compartida” del SDK. Es posible que la nueva versión del cliente intente usar clases que solo existen en las dependencias “compartidas” del SDK más recientes. Pruebe a ejecutar `mvn dependency:tree` o `gradle dependencies` (para Gradle) para verificar que coincidan todas las versiones de la biblioteca del SDK. Para evitar este problema por completo en el futuro, recomendamos utilizar la [lista de materiales (BOM)](setup-project-maven.md#sdk-as-dependency) para administrar versiones de los módulos del SDK.

   El siguiente ejemplo muestra un ejemplo de versiones de SDK mixtas.

   ```
   [INFO] +- software.amazon.awssdk:dynamodb:jar:2.20.00:compile
   [INFO] |  +- software.amazon.awssdk:aws-core:jar:2.13.19:compile
   [INFO] +- software.amazon.awssdk:netty-nio-client:jar:2.20.00:compile
   ```

   La versión de `dynamodb` es 2.20.00 y la versión de `aws-core` es 2.13.19. La versión del artefacto `aws-core` también debería ser 2.20.00.

1. **Compruebe instrucciones al principio de los registros** para ver si una clase no se carga debido a un error de inicialización estática. La primera vez que la clase no se carga, puede generar una excepción diferente y más útil que especifique *por qué* no se puede cargar la clase. Esta excepción, potencialmente útil, se produce solo una vez, por lo que las instrucciones de registro posteriores solo informarán de que no se ha encontrado la clase.

1. **Compruebe el proceso de implementación** para asegurarse de que realmente implementa los archivos JAR necesarios junto con la aplicación. Es posible que esté compilando con la versión correcta, pero el proceso que crea la ruta de clases para su aplicación esté excluyendo una dependencia obligatoria.

## ¿Cómo puedo corregir un error “`SignatureDoesNotMatch`” o un error “The request signature we calculated does not match the signature you provided”?
<a name="faq-signature-does-not-match-error"></a>

Un `SignatureDoesNotMatch` error indica que la firma generada por el AWS SDK para Java y la firma generada por el Servicio de AWS no coinciden. Puede deberse a las causas siguientes.
+ Un proxy o un intermediario modifica la solicitud. Por ejemplo, un proxy o un equilibrador de carga puede modificar un encabezado, una ruta o una cadena de consulta haya firmado el SDK.
+ El servicio y el SDK se diferencian en la forma en que codifican la solicitud cuando cada uno genera la cadena que se va a firmar.

Para solucionar este problema, le recomendamos que [habilite el registro de depuración](logging-slf4j.md#sdk-debug-level-logging) en el SDK. Intente reproducir el error y busque la solicitud canónica que ha generado el SDK. En el registro, la solicitud canónica se etiqueta con `AWS4 Canonical Request: ...` y la cadena que se va a firmar se etiqueta con `AWS4 String to sign: ...`. 

Si no puede habilitar la depuración (por ejemplo, porque solo se puede reproducir en producción), agregue lógica a la aplicación que registra información sobre la solicitud cuando se produzca el error. A continuación, puede usar esa información para intentar replicar el error fuera del entorno de producción en una prueba de integración con el registro de depuración activado.

Una vez recopiladas la solicitud canónica y la cadena de firma, compárelas con la [especificación de la versión 4 de AWS Signature](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) para determinar si hay algún problema en la forma en que el SDK ha generado la cadena de firma. Si algo parece estar mal, puede crear un [informe de GitHub error](https://github.com/aws/aws-sdk-java-v2/issues/new/choose) para AWS SDK para Java. 

Si no hay ningún problema, puedes comparar la cadena del SDK para firmar con la cadena para firmar que algunos Servicios de AWS devuelven como parte de la respuesta al error (Amazon S3, por ejemplo). Si no está disponible, deberá ponerse en [contacto con el servicio afectado](https://aws.amazon.com/contact-us/) para ver qué solicitud canónica y cadena de firma han generado para comparar. Estas comparaciones pueden ayudar a identificar los intermediarios que podrían haber modificado la solicitud o diferencias de codificación entre el servicio y el cliente.

Para obtener más información general sobre la firma de solicitudes, consulte [Firmar solicitudes de AWS API](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html) en la Guía del AWS Identity and Access Management usuario.

**Example de una solicitud canónica**  

```
PUT
/Example-Bucket/Example-Object
partNumber=19&uploadId=string
amz-sdk-invocation-id:f8c2799d-367c-f024-e8fa-6ad6d0a1afb9
amz-sdk-request:attempt=1; max=4
content-encoding:aws-chunked
content-length:51
content-type:application/octet-stream
host:xxxxx
x-amz-content-sha256:STREAMING-UNSIGNED-PAYLOAD-TRAILER
x-amz-date:20240308T034733Z
x-amz-decoded-content-length:10
x-amz-sdk-checksum-algorithm:CRC32
x-amz-trailer:x-amz-checksum-crc32
```

**Example de una cadena de firma**  

```
AWS4-HMAC-SHA256
20240308T034435Z
20240308/us-east-1/s3/aws4_request
5f20a7604b1ef65dd89c333fd66736fdef9578d11a4f5d22d289597c387dc713
```

## ¿Cómo puedo solucionar el error “`java.lang.IllegalStateException`: Connection pool shut down”?
<a name="faq-connection-pool-shutdown-exception"></a>

Este error indica que el grupo de conexiones HTTP de Apache subyacente estaba cerrado. Puede deberse a las causas siguientes.
+ **El cliente del SDK se ha cerrado prematuramente.**El SDK solo cierra el grupo de conexiones cuando el cliente asociado está cerrado. Asegúrese de no cerrar recursos mientras estén en uso.
+ **Se ha lanzado un `java.lang.Error`.** Errores como `OutOfMemoryError` provocan que un grupo de conexiones HTTP de Apache [se cierre](https://github.com/apache/httpcomponents-client/blob/6a741b4f8f23e6c5c7cc42c36c2acabfac19c3d6/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java#L368). Examine sus registros para ver si hay rastros de pilas de error. Revise también el código para ver los lugares en los que capta `Throwable` o `Error`, pero pasa por alto la salida que evita que aparezca el error. Si el código no muestra errores, vuelve a escribirlo para que se registre la información. La información registrada ayuda a determinar la causa raíz del error.
+ **Ha intentado utilizar el proveedor de credenciales del `DefaultCredentialsProvider#create()` después de que se cerró**. [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html#create()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/DefaultCredentialsProvider.html#create())devuelve una instancia singleton, por lo que si está cerrada y el código llama al método `resolveCredentials`, la excepción se generará una vez que caduquen las credenciales (o el token) en caché. 

  Compruebe el código de los lugares donde `DefaultCredentialsProvider` esté cerrado, como se muestra en los siguientes ejemplos.
  + La instancia de singleton se cierra llamando a `DefaultCredentialsProvider#close().`

    ```
    DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // Singleton instance returned.
    AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
    
    // Make calls to Servicios de AWS.
    
    defaultCredentialsProvider.close();  // Explicit close.
    
    // Make calls to Servicios de AWS.
    
    // After the credentials expire, either of the following calls eventually results in a "Connection pool shut down" exception.
    credentials = defaultCredentialsProvider.resolveCredentials();
    // Or
    credentials = DefaultCredentialsProvider.create().resolveCredentials();
    ```
  + Invoca `DefaultCredentialsProvider#create()` en un try-with-resources bloque.

    ```
    try (DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create()) {
        AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
        
        // Make calls to Servicios de AWS.
    
    } // After the try-with-resources block exits, the singleton DefaultCredentialsProvider is closed.
    
    // Make calls to Servicios de AWS.
    
    DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // The closed singleton instance is returned.
    // If the credentials (or token) has expired, the following call results in the error.
    AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
    ```

  Cree una nueva instancia que no sea singleton llamando a `DefaultCredentialsProvider.builder().build()` si el código ha cerrado la instancia de singleton y debe resolver las credenciales mediante un `DefaultCredentialsProvider`.

## ¿Cómo puedo corregir el error «No se pueden cargar las credenciales de ninguno de los proveedores de la cadena AwsCredentialsProviderChain»?
<a name="faq-credentials-provider-chain"></a>

Este error indica que no ha AWS SDK for Java 2.x podido encontrar AWS credenciales válidas a través de ninguno de los proveedores de credenciales de la cadena de proveedores de credenciales predeterminada. El SDK busca automáticamente credenciales en un orden específico y este error se produce cuando todos los proveedores de la cadena no proporcionan credenciales válidas.

El mensaje de error completo suele tener este aspecto (se añaden finales de línea y sangrados para mejorar la legibilidad):

```
Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain(
    credentialsProviders=[
        SystemPropertyCredentialsProvider(),
        EnvironmentVariableCredentialsProvider(), 
        WebIdentityTokenCredentialsProvider(), 
        ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])), 
        ContainerCredentialsProvider(), 
        InstanceProfileCredentialsProvider()
    ]) : [
        SystemPropertyCredentialsProvider(): Unable to load credentials from system settings.
        Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) 
        or system property (aws.accessKeyId)., 

        EnvironmentVariableCredentialsProvider(): Unable to load credentials from system settings. 
        Access key must be specified either via environment variable (AWS_ACCESS_KEY_ID) 
        or system property (aws.accessKeyId)., 

        WebIdentityTokenCredentialsProvider(): To use web identity tokens, the 'sts' service module 
        must be on the class path., 

        ProfileCredentialsProvider(profileName=default, profileFile=ProfileFile(sections=[])): 
        Profile file contained no credentials for profile 'default': ProfileFile(sections=[]), 

        ContainerCredentialsProvider(): Cannot fetch credentials from container - neither 
        AWS_CONTAINER_CREDENTIALS_FULL_URI or AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment 
        variables are set., 

        InstanceProfileCredentialsProvider(): Failed to load credentials from IMDS.]
```

### Problemas y soluciones comunes
<a name="faq-cred-provider-chain-common-causes-and-solutions"></a>

#### Revise la configuración de sus credenciales
<a name="faq-cred-provider-chain-check-config"></a>

Cuando utiliza el proveedor de credenciales predeterminado (llamando a `ServiceClient.create()` sin configurar credenciales de forma explícita), el SDK busca credenciales en un orden específico. Revise [cómo funciona la cadena de proveedores predeterminados de credenciales](credentials-chain.md) para comprender qué fuentes de credenciales comprueba el SDK y en qué orden.

Asegúrese de que el método de configuración de credenciales que desea utilizar esté configurado correctamente en su entorno:

##### Para instancias de Amazon EC2
<a name="faq-cred-check-ec2"></a>
+ **Compruebe el rol de IAM:** compruebe que haya un rol de IAM asociado a la instancia.
+ **Fallos intermitentes del IMDS**: si se producen fallos intermitentes (que suelen durar unos cientos de milisegundos), suele deberse a problemas transitorios de red que afectan al servicio de metadatos de instancias (IMDS).

  Soluciones:
  + Habilite el [registro de depuración](logging-slf4j.md#sdk-debug-level-logging) para analizar el tiempo y la frecuencia de los fallos
  + Considere la posibilidad de implementar lógica de reintento en la aplicación para errores relacionados con credenciales
  + Compruebe si hay problemas de conectividad de red entre la instancia y el punto de conexión del IMDS

##### Para entornos de contenedores
<a name="faq-cred-check-container-env"></a>

Confirme que los roles de tareas (Amazon ECS) o las cuentas de servicio (Amazon EKS) estén configuradas y que las variables de entorno necesarias estén configuradas.

##### Para desarrollo local
<a name="faq-cred-check-local-dev"></a>

Compruebe que las variables de entorno, los archivos de credenciales o la configuración del Centro de identidades de IAM están definidos.

##### Para federación de identidades web
<a name="faq-cred-check-web-id-federation"></a>
+ **Compruebe la configuración:** compruebe que existe el archivo de token de identidad web y que están configuradas las variables de entorno necesarias.
+ **Falta la dependencia del módulo STS:** si aparece el error `To use web identity tokens, the 'sts' service module must be on the class path`, debe agregar el módulo STS como dependencia. Esto es habitual cuando se utiliza Pod Identity de Amazon EKS u otra autenticación de token de identidad web.

  Solución: añada el módulo STS a las dependencias de su proyecto:
  + 

    ```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>sts</artifactId>
    </dependency>
    ```

    Para algunos servicios, es posible que también necesite la dependencia de `aws-query-protocol`:

    ```
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>aws-query-protocol</artifactId>
    </dependency>
    ```

#### Problemas de conectividad de red o de proxy
<a name="faq-credentials-provider-chain-network-issues"></a>

Si aparecen errores `Connection refused` en la cadena de proveedores de credenciales, suele deberse a problemas de conectividad de red cuando el SDK intenta llegar a los puntos de conexión de AWS .

**Soluciones:**
+ Compruebe la configuración del proxy si utiliza un servidor proxy
+ Compruebe que su red permita conexiones HTTPS salientes a los puntos finales AWS 
+ Habilite [registro de depuración](logging-slf4j.md#sdk-debug-level-logging) para ver los intentos de conexión detallados
+ Pruebe la conectividad mediante herramientas como `curl` para verificar el acceso de red a los puntos de conexión de AWS 

# Reduzca el tiempo de inicio del SDK para AWS Lambda
<a name="lambda-optimize-starttime"></a>

Uno de los objetivos del AWS SDK for Java 2.x es reducir la latencia de inicio de las AWS Lambda funciones. El SDK contiene cambios que reducen el tiempo de startup, descritos al final de este tema.

En primer lugar, este tema se centra en los cambios que puede realizar para reducir los tiempos de arranque en frío. Esto incluye realizar cambios en la estructura de su código y en la configuración de los clientes del servicio.

## Utilice un cliente HTTP AWS basado en CRT
<a name="lambda-quick-url"></a>

Para trabajar con él AWS Lambda, recomendamos el [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtHttpClient.html)para escenarios sincrónicos y [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.html)asíncronos.

El tema [Configurar clientes AWS HTTP basados en CRT](http-configuration-crt.md) de esta guía describe las ventajas de usar los clientes de HTTP, cómo agregar la dependencia y cómo configurar su uso por los clientes de servicio. 

## Eliminar las dependencias del cliente HTTP no utilizadas
<a name="lambda-quick-remove-deps"></a>

Además del uso explícito de un cliente AWS basado en CRT, puedes eliminar otros clientes HTTP que el SDK incluye de forma predeterminada. El tiempo de startup de Lambda se reduce cuando se necesita cargar menos librerías, por lo que debería eliminar cualquier artefacto no utilizado que la JVM necesite cargar.

El siguiente fragmento de código de un archivo `pom.xml` Maven muestra la exclusión del cliente HTTP basado en Apache y el cliente HTTP basado en Netty. (Estos clientes no son necesarios cuando se utiliza un cliente basado en AWS CRT). En este ejemplo, se excluyen los artefactos del cliente HTTP de la dependencia del cliente S3 y se agrega el `aws-crt-client` artefacto para permitir el acceso a los AWS clientes HTTP basados en CRT.

```
<project>
    <properties>
        <aws.java.sdk.version>2.27.21</aws.java.sdk.version>
    <properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>${aws.java.sdk.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>aws-crt-client</artifactId>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>s3</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>software.amazon.awssdk</groupId>
                    <artifactId>netty-nio-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>software.amazon.awssdk</groupId>
                    <artifactId>apache-client</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
</project>
```

**nota**  
Añada el elemento `<exclusions>` a todas las dependencias del cliente de servicio del archivo `pom.xml`.

## Configurar los clientes de servicio para abreviar las búsquedas
<a name="lambda-quick-clients"></a>

**Especificar una región **  
Cuando cree un cliente de servicio, llame al método `region` en el generador del cliente de servicio. Esto reduce el [proceso de búsqueda de regiones](region-selection.md#default-region-provider-chain) predeterminado del SDK, que busca la información en varios lugares. Región de AWS   
Para mantener el código Lambda independiente de la región, utilice el siguiente código dentro del método `region`. Este código accede a la variable de entorno `AWS_REGION` establecida por el contenedor Lambda.  

```
Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))
```

**Utilizar `EnvironmentVariableCredentialProvider`**  
Al igual que el comportamiento de búsqueda predeterminado para la información de la Región, el SDK busca las credenciales en varios lugares. Si especifica el [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/EnvironmentVariableCredentialsProvider.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/auth/credentials/EnvironmentVariableCredentialsProvider.html) al generar un cliente de servicio, ahorrará tiempo en el proceso de búsqueda de credenciales del SDK.  
El uso de este proveedor de credenciales permite que el código se utilice en Lambda funciones, pero es posible que no funcione en Amazon EC2 otros sistemas.  
Si piensa utilizar [Lambda SnapStart para Java](#lambda-quick-snapstart) en algún momento, debe confiar en la cadena de proveedores de credenciales predeterminada para buscar las credenciales. Si lo especifica`EnvironmentVariableCredentialsProvider`, la búsqueda inicial de credenciales funciona, pero cuando SnapStart se activa, [el motor de ejecución de Java establece las variables de entorno de las credenciales del contenedor](https://docs.aws.amazon.com/lambda/latest/dg/snapstart-activate.html#snapstart-credentials). Tras la activación, las variables de entorno utilizadas por `EnvironmentVariableCredentialsProvider` (variables de entorno clave de acceso) no están disponibles en el SDK de Java.

El siguiente fragmento de código muestra un cliente de servicio S3 configurado adecuadamente para su uso en un entorno Lambda.

```
S3Client s3Client = S3Client.builder()
    .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable())))
    .credentialsProvider(EnvironmentVariableCredentialsProvider.create())
    .httpClient(AwsCrtHttpClient.builder().build())
    .build();
```

## Inicializar el cliente de SDK fuera del controlador de la función de Lambda
<a name="lambda-quick-initialize"></a>

Recomendamos inicializar un cliente SDK fuera del método del controlador Lambda. De esta forma, si se reutiliza el contexto de ejecución, se puede omitir la inicialización del cliente de servicio. Al reutilizar la instancia del cliente y sus conexiones, las invocaciones posteriores al método controlador se producen más rápidamente.

En el siguiente ejemplo, la instancia `S3Client` se inicializa en el generador mediante un método de fábrica estático. Si se reutiliza el contenedor que administra el entorno Lambda, se reutiliza la instancia `S3Client` inicializada.

```
public class App implements RequestHandler<Object, Object> {
    private final S3Client s3Client;

    public App() {
        s3Client = DependencyFactory.s3Client();
    }

    @Override
    public Object handle Request(final Object input, final Context context) {
         ListBucketResponse response = s3Client.listBuckets();
         // Process the response.
    }
}
```

## Minimizar la inyección de dependencias
<a name="lambda-quick-di"></a>

Los marcos de inyección de dependencias (DI) pueden tardar más tiempo en completar el proceso de configuración. También es posible que requieran dependencias adicionales, que tardan un tiempo en cargarse.

Si se necesita un marco de DI, recomendamos usar marcos DI livianos como [Dagger](https://dagger.dev/dev-guide/).

## Utilice una segmentación por arquetipo de Maven AWS Lambda
<a name="lambda-quick-maven"></a>

El equipo del SDK de AWS Java ha desarrollado una plantilla [Maven Archetype](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda) para arrancar un proyecto Lambda con un tiempo de inicio mínimo. Puede crear un proyecto de Maven a partir del arquetipo y saber que las dependencias están configuradas adecuadamente para el entorno de Lambda. 

Para obtener más información sobre el arquetipo y trabajar con un ejemplo de implementación, consulte esta [entrada del blog](https://aws.amazon.com/blogs/developer/bootstrapping-a-java-lambda-application-with-minimal-aws-java-sdk-startup-time-using-maven/).

## Considere Lambda SnapStart para Java
<a name="lambda-quick-snapstart"></a>

Si sus requisitos de tiempo de ejecución son compatibles, AWS ofrece [Lambda SnapStart para Java](https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html). Lambda SnapStart es una solución basada en infraestructura que mejora el rendimiento inicial de las funciones de Java. Al publicar una nueva versión de una función, Lambda la SnapStart inicializa y toma una instantánea cifrada e inmutable del estado de la memoria y del disco. SnapStart a continuación, guarda en caché la instantánea para volver a utilizarla.

## Cambios en la versión 2.x que afectan al tiempo de startup
<a name="example-client-configuration"></a>

Además de los cambios que haga en su código, la versión 2.x del SDK para Java incluye tres cambios principales que reducen el tiempo de startup:
+ Uso de [jackson-jr](https://github.com/FasterXML/jackson-jr), una biblioteca de serialización que mejora el tiempo de inicialización.
+ Uso de las bibliotecas [java.time](https://docs.oracle.com/javase/8/docs/api/index.html?java/time.html) para los objetos de fecha y hora, parte del JDK.
+ Uso de [Slf4j](https://www.slf4j.org/) para una fachada de registro.

## Recursos adicionales
<a name="lambda-quick-resources"></a>

La Guía para AWS Lambda desarrolladores contiene una [sección sobre las mejores prácticas](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html) para desarrollar funciones de Lambda que no es específica de Java.

Para ver un ejemplo de cómo crear una aplicación nativa de la nube en Java que utilice Java AWS Lambda, consulte el contenido de este [taller](https://github.com/aws-samples/aws-lambda-java-workshop). En el taller se trata la optimización del rendimiento y otras buenas prácticas.

Puede considerar la posibilidad de utilizar imágenes estáticas que se compilen con antelación para reducir la latencia de startup. Por ejemplo, puede usar el SDK para Java 2.x y Maven para [generar una imagen nativa de GraalVM](setup-project-graalvm.md).

# Implemente `ContentStreamProvider` en el AWS SDK for Java 2.x
<a name="content-stream-provider"></a>

`ContentStreamProvider`es una abstracción utilizada en el AWS SDK for Java 2.x para permitir múltiples lecturas de los datos de entrada. En este tema se explica cómo implementar un `ContentStreamProvider` correctamente para las aplicaciones.

El SDK para Java 2.x usa el método `ContentStreamProvider#newStream()` cada vez que necesita leer un flujo completo. Para que esto funcione en todo el flujo, el flujo devuelto debe estar siempre al principio del contenido y debe contener los mismos datos. 

En las secciones siguientes, proporcionaremos tres métodos para implementar correctamente este comportamiento.

## Utilice `mark()` y `reset()`
<a name="csp-impl-mark-reset"></a>

En el siguiente ejemplo, utilizamos `mark(int)` en el constructor antes de que comience la lectura para asegurarnos de que podemos restablecer el flujo al principio. Para cada invocación de `newStream()`, restablecemos el flujo:

```
public class MyContentStreamProvider implements ContentStreamProvider {  
    private InputStream contentStream;  
  
    public MyContentStreamProvider(InputStream contentStream) {  
        this.contentStream = contentStream;  
        this.contentStream.mark(MAX_LEN);  
    }  
  
    @Override  
    public InputStream newStream() {  
        contentStream.reset();  
        return contentStream;  
    }  
}
```

## Uso de almacenamiento en búfer si `mark()` y `reset()` no están disponibles
<a name="csp-impl-unsupported-streams"></a>

 Si el flujo no es compatible con `mark()` y `reset()` directamente, puede seguir usando la solución que se mostró anteriormente envolviendo primero el flujo en un `BufferedInputStream`:

```
public class MyContentStreamProvider implements ContentStreamProvider {  
    private BufferedReader contentStream;  
  
    public MyContentStreamProvider(InputStream contentStream) {  
        this.contentStream = new BufferedInputStream(contentStream);  
        this.contentStream.mark(MAX_LEN);
    }  
  
    @Override  
    public InputStream newStream() {  
        contentStream.reset();  
        return contentStream;  
    }  
}
```

## Creación de nuevos flujos
<a name="csp-impl-new-stream"></a>

Un método más sencillo consiste simplemente en obtener un nuevo flujo para los datos en cada invocación y cerrar el anterior:

```
public class MyContentStreamProvider implements ContentStreamProvider {  
    private InputStream contentStream;  
  
    @Override  
    public InputStream newStream() {  
        if (contentStream != null) {  
            contentStream.close();  
        }  
        contentStream = openStream();  
        return contentStream;  
    }  
}
```

# Configurar el TTL de JVM para las búsquedas de nombres DNS
<a name="jvm-ttl-dns"></a>

La máquina virtual de Java (JVM) almacena en caché las búsquedas de nombres DNS. Cuando la JVM resuelve un nombre de host en una dirección IP, almacena en caché la dirección IP durante un período de tiempo específico, conocido como TTL *time-to-live*.

Como AWS los recursos utilizan entradas de nombres DNS que cambian de vez en cuando, le recomendamos que configure la JVM con un valor TTL de 5 segundos. Con esto se asegurará de que cuando cambie la dirección IP de un recurso, su aplicación pueda recibir y utilizar la nueva dirección IP del recurso volviendo a consultar el DNS.

En algunas configuraciones de Java, el TTL predeterminado de JVM está establecido de forma que *nunca* se actualicen las entradas DNS hasta que se reinicie la JVM. Por lo tanto, si la dirección IP de un AWS recurso cambia mientras la aplicación aún se está ejecutando, no podrá usar ese recurso hasta que *reinicie manualmente la JVM y se actualice* la información de IP almacenada en caché. En este caso, es fundamental establecer el TTL de la JVM de forma que actualice periódicamente la información de las direcciones IP almacenada en caché.

## Cómo configurar el TTL de JVM
<a name="how-to-set-the-jvm-ttl"></a>

[Para modificar el TTL de la JVM, defina el valor de la propiedad de seguridad networkaddress.cache.ttl.](https://docs.oracle.com/en/java/javase/17/core/java-networking.html#GUID-A680DADB-C4C1-40F1-B568-D9A97C917F5D) Tenga en cuenta que `networkaddress.cache.ttl` es una propiedad de *seguridad, no una propiedad* del sistema, es decir, no se puede configurar con el indicador de línea de comandos. `-D`

### Opción 1: configúrelo mediante programación en su aplicación
<a name="set-ttl-programmatically"></a>

Llama al [https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/Security.html](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/Security.html)principio de la aplicación, antes de crear cualquier cliente AWS del SDK y antes de realizar cualquier solicitud de red:

```
import java.security.Security;

public class MyApplication {
    public static void main(String[] args) {
        Security.setProperty("networkaddress.cache.ttl", "5");

        // ... create SDK clients and run application
    }
}
```

### Opción 2: configúrelo en el archivo java.security
<a name="set-ttl-java-security-file"></a>

Establezca la `networkaddress.cache.ttl` propiedad en el `$JAVA_HOME/jre/lib/security/java.security` archivo para Java 8 o en `$JAVA_HOME/conf/security/java.security` el archivo para Java 11 o superior.

A continuación se ofrece muestra un fragmento de archivo `java.security` que muestra la caché de TTL configurada en 5 segundos.

```
#
# The Java-level namelookup cache policy for successful lookups:
#
# any negative value: caching forever
# any positive value: the number of seconds to cache an address for
# zero: do not cache
#
...
networkaddress.cache.ttl=5
...
```

Todas las aplicaciones que se ejecutan en la JVM representada por la variable de `$JAVA_HOME` entorno utilizan esta configuración.

### Opción 3: Utilice la opción alternativa de propiedades del sistema JDK (línea de comandos)
<a name="set-ttl-system-property"></a>

Si no puede modificar la configuración o el código de seguridad, puede utilizar las propiedades del sistema JDK. Actúan como alternativas si no se ha definido ninguna propiedad de seguridad.
+ `sun.net.inetaddr.ttl`— Controla las búsquedas correctas (TTL positivo)
+ `sun.net.inetaddr.negative.ttl`— Controla las búsquedas fallidas (TTL negativo)

```
java -Dsun.net.inetaddr.ttl=5 -Dsun.net.inetaddr.negative.ttl=1 -jar myapp.jar
```

**nota**  
Se trata de propiedades internas del JDK documentadas en la referencia de [Oracle Java 8 Networking Properties como propiedades](https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html) privadas que «es posible que no se admitan en futuras versiones». Utilice las opciones 1 y 2 siempre que sea posible.

# Trabajar con HTTP/2 en el AWS SDK para Java
<a name="http2"></a>

HTTP/2 es una revisión importante del protocolo HTTP. Esta nueva versión tiene varias mejoras para optimizar el rendimiento:
+ La codificación de datos binarios permite una transferencia de datos más eficiente.
+ La compresión de encabezado reduce la sobrecarga de bytes descargados por el cliente, lo que ayuda a que el cliente obtenga el contenido antes. Esto resulta especialmente útil para los clientes móviles que ya tienen un ancho de banda limitado.
+ La comunicación asíncrona bidireccional (multiplexado) permite que varias solicitudes y mensajes de respuesta entre el cliente y AWS estén en tránsito al mismo tiempo en una única conexión, en vez de necesitar varias conexiones, lo que mejora el rendimiento.

Los desarrolladores que actualizan a los SDK más recientes utilizarán automáticamente HTTP/2 cuando sea compatible con el servicio con el que estén trabajando. Las nuevas interfaces de programación aprovechan fácilmente las características de HTTP/2 y proporcionan nuevas formas de crear aplicaciones.

El AWS SDK para Java 2.x incluye nuevas API para streaming de eventos que implementan el protocolo HTTP/2. Para ver ejemplos de cómo usar estas nuevas API, consulte [Trabajar con Kinesis](examples-kinesis.md).