

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Usar o SDK do
<a name="using"></a>

Esta seção fornece as informações básicas necessárias para usar AWS SDK para Kotlin o.

**Topics**
+ [Fazer solicitações.](making-requests.md)
+ [Corrotinas](coroutines.md)
+ [Operações de streaming](streaming-ops.md)
+ [Paginação](pagination.md)
+ [Waiters](waiters.md)
+ [Tratamento de erros](error-handling.md)
+ [Solicitações pré-assinadas](presign-requests.md)
+ [Solução de problemas FAQs](troubleshooting-faqs.md)
+ [Zombando no AWS SDK para Kotlin](mocking.md)

# Fazer solicitações.
<a name="making-requests"></a>

Use um cliente de serviço para fazer solicitações a um AWS service (Serviço da AWS). O AWS SDK para Kotlin fornece idiomas específicos de domínio (DSLs) seguindo um padrão de [construtor de tipos seguros](https://kotlinlang.org/docs/type-safe-builders.html) para criar solicitações. Estruturas aninhadas de solicitações também podem ser acessadas por meio de seus. DSLs

O exemplo a seguir mostra como criar uma entrada de operação CreateTable [do Amazon DynamoDB](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/dynamodb/aws.sdk.kotlin.services.dynamodb/create-table.html):

```
val ddb = DynamoDbClient.fromEnvironment()

val req = CreateTableRequest {
    tableName = name
    keySchema = listOf(
        KeySchemaElement {
            attributeName = "year"
            keyType = KeyType.Hash
        },
        KeySchemaElement {
            attributeName = "title"
            keyType = KeyType.Range
        }
    )

    attributeDefinitions = listOf(
        AttributeDefinition {
            attributeName = "year"
            attributeType = ScalarAttributeType.N
        },
        AttributeDefinition {
            attributeName = "title"
            attributeType = ScalarAttributeType.S
        }
    )
    
    // You can configure the `provisionedThroughput` member
    // by using the `ProvisionedThroughput.Builder` directly:
    provisionedThroughput {
        readCapacityUnits = 10
        writeCapacityUnits = 10
    }
}

val resp = ddb.createTable(req)
```

## Sobrecargas DSL da interface de serviço
<a name="service-interface-dsl-overloads"></a>

Cada operação sem streaming na interface do cliente de serviço tem uma sobrecarga de DSL para que você não precise criar uma solicitação separada.

Exemplo de criação de um bucket do Amazon Simple Storage Service (Amazon S3) com a função sobrecarregada:

```
s3Client.createBucket {    // this: CreateBucketRequest.Builder
    bucket = newBucketName
}
```

Isso é equivalente a:

```
val request = CreateBucketRequest {    // this: CreateBucketRequest.Builder 
    bucket = newBucketName 
}

s3client.createBucket(request)
```

## Solicitações sem entradas necessárias
<a name="requests-no-required-inputs"></a>

As operações que não têm entradas obrigatórias podem ser chamadas sem a necessidade de passar por um objeto de solicitação. Isso geralmente é possível com operações do tipo lista, como a operação da API Amazon `listBuckets` S3.

 Por exemplo, as três declarações a seguir são equivalentes: 

```
s3Client.listBuckets(ListBucketsRequest {
  // Construct the request object directly.
})
s3Client.listBuckets {
  // DSL builder without explicitly setting any arguments.
}
s3Client.listBuckets()
```

# Corrotinas
<a name="coroutines"></a>

O AWS SDK para Kotlin é assíncrono por padrão. O SDK para Kotlin usa `suspend` funções para todas as operações, que devem ser chamadas a partir de uma corrotina. 

Para obter um guia mais detalhado sobre corrotinas, consulte a documentação [oficial](https://kotlinlang.org/docs/coroutines-overview.html) do Kotlin.

## Fazendo solicitações simultâneas
<a name="making-concurrent-requests"></a>

O construtor de corrotinas [assíncronas](https://kotlinlang.org/docs/composing-suspending-functions.html#concurrent-using-async) pode ser usado para iniciar solicitações simultâneas nas quais você se preocupa com os resultados. `async`retorna um [Deferred](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-deferred/index.html), que representa um future leve e sem bloqueios que representa a promessa de fornecer um resultado posteriormente.

Se você não se importa com os resultados (apenas com a conclusão de uma operação), você pode usar o construtor de corrotinas de [inicialização](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html). `launch`é conceitualmente semelhante a. `async` A diferença é que o launch retorna um [Job](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-job/index.html) e não carrega nenhum valor resultante, enquanto `async` retorna `Deferred` a.

Veja a seguir um exemplo de como fazer solicitações simultâneas para o Amazon S3 usando a operação HeadObject para obter [o](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/head-object.html) tamanho do conteúdo de duas chaves:

```
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis
import aws.sdk.kotlin.services.s3.S3Client


fun main(): Unit = runBlocking {

    val s3 = S3Client { region = "us-east-2" }
    
    val myBucket = "<your-bucket-name-here>"
    val key1 = "<your-object-key-here>"
    val key2 = "<your-second-object-key-here>"

    val resp1 = async {
        s3.headObject{
            bucket = myBucket
            key = key1
        }
    }

    val resp2 = async {
        s3.headObject{
            bucket = myBucket
            key = key2
        }
    }


    val elapsed = measureTimeMillis {
        val totalContentSize = resp1.await().contentLength + resp2.await().contentLength
        println("content length of $key1 + $key2 = $totalContentSize")
    }

    println("requests completed in $elapsed ms")

}
```

## Fazendo solicitações de bloqueio
<a name="making-clocking-requests"></a>

[Para fazer chamadas de serviço a partir de código existente que não usa corrotinas e implementa um modelo de encadeamento diferente, você pode usar o construtor de corrotinas RunBlocking.](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html) Um exemplo de um modelo de segmentação diferente é usar a executors/futures abordagem tradicional do Java. Talvez seja necessário usar essa abordagem se estiver combinando código ou bibliotecas Java e Kotlin. 

Como o próprio nome sugere, esse `runBlocking` construtor lança uma nova corrotina e bloqueia o encadeamento atual até que ele seja concluído. 

**Atenção**  
 `runBlocking`geralmente não deve ser usado a partir de uma corrotina. Ele foi projetado para conectar o código de bloqueio regular às bibliotecas escritas em estilo suspenso (como nas funções e testes principais). 

# Operações de streaming
<a name="streaming-ops"></a>

No AWS SDK para Kotlin, os dados binários (fluxos) são representados como um [https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.content/-byte-stream/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/runtime-core/aws.smithy.kotlin.runtime.content/-byte-stream/index.html)tipo, que é um fluxo abstrato de bytes somente para leitura.

## Respostas de streaming
<a name="streaming-responses"></a>

As respostas com um stream binário (como a operação de API do Amazon Simple Storage Service (Amazon [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)S3)) são tratadas de forma diferente de outros métodos. Esses métodos usam uma função lambda que manipula a resposta em vez de retorná-la diretamente. Isso limita o escopo da resposta à função e simplifica o gerenciamento da vida útil do chamador e do tempo de execução do SDK.

Depois que a função lambda retorna, todos os recursos, como a conexão HTTP subjacente, são liberados. (Eles não `ByteStream` devem ser acessados após o retorno do lambda e não devem ser retirados do fechamento.) O resultado da chamada é o que o lambda retorna.

O exemplo de código a seguir mostra a função [getObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/-s3-client/get-object.html) recebendo um parâmetro lambda, que manipula a resposta.

```
val s3Client = S3Client.fromEnvironment()
val req = GetObjectRequest { ... }

val path = Paths.get("/tmp/download.txt")

// S3Client.getObject has the following signature:
// suspend fun <T> getObject(input: GetObjectRequest, block: suspend (GetObjectResponse) -> T): T

val contentSize = s3Client.getObject(req) { resp ->
    // resp is valid until the end of the block.
    // Do not attempt to store or process the stream after the block returns.
    
    // resp.body is of type ByteStream.
    val rc = resp.body?.writeToFile(path)
    rc
}
println("wrote $contentSize bytes to $path")
```

O `ByteStream` tipo tem as seguintes extensões para formas comuns de consumi-lo:
+ `ByteStream.writeToFile(file: File): Long`
+ `ByteStream.writeToFile(path: Path): Long`
+ `ByteStream.toByteArray(): ByteArray`
+ `ByteStream.decodeToString(): String`

Tudo isso está definido no `aws.smithy.kotlin.runtime.content` pacote.

## Solicitações de streaming
<a name="streaming-requests"></a>

Para fornecer um`ByteStream`, também existem vários métodos de conveniência, incluindo os seguintes:
+ `ByteStream.fromFile(file: File)`
+ `File.asByteStream(): ByteStream`
+ `Path.asByteStream(): ByteStream`
+ `ByteStream.fromBytes(bytes: ByteArray)`
+ `ByteStream.fromString(str: String)`

Tudo isso está definido no `aws.smithy.kotlin.runtime.content` pacote.

O exemplo de código a seguir mostra o uso de métodos de `ByteStream` conveniência que fornecem a propriedade body na criação de um [PutObjectRequest](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.model/-put-object-request/index.html):

```
val req = PutObjectRequest {
    ...
    body = ByteStream.fromFile(file)
    // body = ByteStream.fromBytes(byteArray)
    // body = ByteStream.fromString("string")
    // etc
}
```

# Paginação
<a name="pagination"></a>

Muitas AWS operações retornam resultados paginados quando a carga é muito grande para ser retornada em uma única resposta. AWS SDK para Kotlin Inclui [extensões](https://kotlinlang.org/docs/extensions.html) para a interface do cliente de serviço que paginam automaticamente os resultados para você. Você precisa somente escrever o código que processará os resultados.

A paginação é exposta como um [fluxo](https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/) <T>para que você possa aproveitar as transformações idiomáticas do Kotlin para coleções assíncronas (como, e). `map` `filter` `take` As exceções são transparentes, o que faz com que o tratamento de erros pareça uma chamada normal de API, e o cancelamento segue o cancelamento cooperativo geral de corotinas. Para obter mais informações, consulte [fluxos](https://kotlinlang.org/docs/flow.html) e [exceções de fluxo](https://kotlinlang.org/docs/flow.html#flow-exceptions) no guia oficial.

**nota**  
Os exemplos a seguir usam o Amazon S3. No entanto, os conceitos são os mesmos para qualquer serviço que tenha um ou mais APIs paginados. Todas as extensões de paginação são definidas no `aws.sdk.kotlin.services.<service>.paginators` pacote (como`aws.sdk.kotlin.services.dynamodb.paginators`). 

O exemplo de código a seguir mostra como você pode processar a resposta paginada da chamada da função [ListObjectsV2Paginated](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.paginators/list-objects-v2-paginated.html). 

**Importações**

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.paginators.listObjectsV2Paginated
import kotlinx.coroutines.flow.*
```

**Código**

```
val s3 = S3Client.fromEnvironment()
val req = ListObjectsV2Request {
    bucket = "amzn-s3-demo-bucket"
    maxKeys = 1
}

s3.listObjectsV2Paginated(req)  // Flow<ListObjectsV2Response>
    .transform { it.contents?.forEach { obj -> emit(obj) } }
    .collect { obj ->
        println("key: ${obj.key}; size: ${obj.size}")
    }
```

# Waiters
<a name="waiters"></a>

Os waiters são uma abstração do lado do cliente usados para sondar um recurso da até que o estado desejado seja atingido ou até que seja determinado que o recurso não entrará no estado desejado. Essa é uma tarefa comum quando se trabalha com serviços que acabam sendo consistentes, como o Amazon Simple Storage Service (Amazon S3), ou serviços que criam recursos de forma assíncrona, como o Amazon EC2. 

Escrever uma lógica para sondar continuamente o status de um recurso pode ser complicado e propenso a erros. O objetivo dos garçons é transferir essa responsabilidade do código do cliente para o AWS SDK para Kotlin, que tem um conhecimento profundo dos aspectos de cronometragem da operação. AWS 

**nota**  
Os exemplos a seguir usam o Amazon S3. No entanto, os conceitos são os mesmos para qualquer AWS service (Serviço da AWS) que tenha um ou mais waiters definidos. Todas as extensões são definidas no `aws.sdk.kotlin.services.<service>.waiters` pacote (como`aws.sdk.kotlin.services.dynamodb.waiters`). Eles também seguem uma convenção de nomenclatura padrão (`waitUntil<Condition>`).

O exemplo de código a seguir mostra o uso de uma função de espera que permite evitar escrever a lógica de pesquisa.

**Importações**

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.waiters.waitUntilBucketExists
```

**Código**

```
val s3 = S3Client.fromEnvironment()

// This initiates creating an S3 bucket and potentially returns before the bucket exists.
s3.createBucket { bucket = "amzn-s3-demo-bucket" }

// When this function returns, the bucket either exists or an exception
// is thrown.
s3.waitUntilBucketExists { bucket = "amzn-s3-demo-bucket" }

// The bucket now exists.
```

**nota**  
Cada método de espera retorna uma `Outcome` instância que pode ser usada para obter a resposta final que corresponde ao alcance da condição desejada. Um resultado também contém detalhes adicionais, como o número de tentativas feitas para alcançar o estado desejado.

# Tratamento de erros
<a name="error-handling"></a>

Entender como e quando AWS SDK para Kotlin as exceções são lançadas é importante para criar aplicativos de alta qualidade usando o SDK. As seções a seguir descrevem os casos diferentes de exceções lançadas pelo SDK e como processá-las da maneira apropriada.

## Exceções de serviço
<a name="service-exceptions"></a>

A exceção mais comum é`AwsServiceException`, da qual todas as exceções específicas do serviço (como`S3Exception`) são herdadas. Essa exceção representa uma resposta de erro de um AWS service (Serviço da AWS). Por exemplo, se você tentar encerrar uma EC2 instância da Amazon que não existe, a Amazon EC2 retornará uma resposta de erro. Os detalhes da resposta ao erro estão incluídos no `AwsServiceException` que foi lançado. 

Quando você encontra um`AwsServiceException`, isso significa que sua solicitação foi enviada com sucesso para o AWS service (Serviço da AWS) , mas não pôde ser processada. Isso pode ocorrer devido a erros nos parâmetros da solicitação ou problemas no lado do serviço.

## Exceções do cliente
<a name="client-exceptions"></a>

`ClientException`indica que ocorreu um problema dentro do código do AWS SDK para Kotlin cliente, ao tentar enviar uma solicitação para AWS ou ao tentar analisar uma resposta do AWS. `ClientException`A geralmente é mais grave do que a `AwsServiceException` e indica que um grande problema está impedindo o cliente de processar as chamadas de serviço para Serviços da AWS o. Por exemplo, ele AWS SDK para Kotlin lança um `ClientException` se não conseguir analisar uma resposta de um serviço.

## Metadados de erro
<a name="error-metadata"></a>

Cada exceção de serviço e exceção de cliente tem a `sdkErrorMetadata` propriedade. Esse é um pacote de propriedades digitado que pode ser usado para recuperar detalhes adicionais sobre o erro.

Existem várias extensões predefinidas diretamente para o `AwsErrorMetadata` tipo, incluindo, mas não se limitando às seguintes:
+ `sdkErrorMetadata.requestId`— o ID de solicitação exclusivo
+ `sdkErrorMetadata.errorMessage`— a mensagem legível por humanos (geralmente corresponde à`Exception.message`, mas pode conter mais informações se a exceção for desconhecida pelo serviço)
+ `sdkErrorMetadata.protocolResponse`— A resposta bruta do protocolo

O exemplo a seguir demonstra o acesso aos metadados de erro.

```
try {
    s3Client.listBuckets { ... }
} catch (ex: S3Exception) {
    val awsRequestId = ex.sdkErrorMetadata.requestId
    val httpResp = ex.sdkErrorMetadata.protocolResponse as? HttpResponse

    println("requestId was: $awsRequestId")
    println("http status code was: ${httpResp?.status}")
}
```

# Solicitações pré-assinadas
<a name="presign-requests"></a>

Você pode pré-assinar solicitações para algumas operações de AWS API para que outro chamador possa usar a solicitação posteriormente sem apresentar suas próprias credenciais. 

Por exemplo, suponha que Alice tenha acesso a um objeto do Amazon Simple Storage Service (Amazon S3) e queira compartilhar temporariamente o acesso ao objeto com Bob. Alice pode gerar uma `GetObject` solicitação pré-assinada para compartilhar com Bob para que ele possa baixar o objeto sem precisar acessar as credenciais de Alice.

## Conceitos básicos de pré-assinatura
<a name="presign-requests-basics"></a>

O SDK para Kotlin fornece métodos de extensão em clientes de serviço para pré-assinar solicitações. Todas as solicitações pré-assinadas exigem uma duração que represente por quanto tempo a solicitação assinada é válida. Após o término da duração, a solicitação pré-assinada expira e gera um erro de autenticação se executada.

O código a seguir mostra um exemplo que cria uma `GetObject` solicitação pré-assinada para o Amazon S3. A solicitação é válida por 24 horas após a criação.

```
val s3 = S3Client.fromEnvironment()

val unsignedRequest = GetObjectRequest {
    bucket = "foo"
    key = "bar"
}

val presignedRequest = s3.presignGetObject(unsignedRequest, 24.hours)
```

O método [https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-get-object.html](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-get-object.html)de extensão retorna um [https://docs.aws.amazon.com/smithy-kotlin/api/latest/http/aws.smithy.kotlin.runtime.http.request/-http-request/index.html](https://docs.aws.amazon.com/smithy-kotlin/api/latest/http/aws.smithy.kotlin.runtime.http.request/-http-request/index.html)objeto. O objeto de solicitação contém o URL pré-assinado em que a operação pode ser invocada. Outro chamador pode usar a URL (ou a solicitação inteira) em uma base de código ou ambiente de linguagem de programação diferente.

Depois de criar a solicitação pré-assinada, use um cliente HTTP para invocar uma solicitação. A API para invocar uma solicitação HTTP GET depende do cliente HTTP. O exemplo a seguir usa o método Kotlin [https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.net.-u-r-l/read-text.html](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.net.-u-r-l/read-text.html).

```
val objectContents = URL(presignedRequest.url.toString()).readText()
println(objectContents)
```

## Configuração avançada de pré-assinatura
<a name="presign-requests-conf-advanced"></a>

No SDK, cada método que pode pré-assinar solicitações tem uma sobrecarga que você pode usar para fornecer opções de configuração avançadas, como uma implementação específica do signatário ou parâmetros de assinatura detalhados.

O exemplo a seguir mostra uma `GetObject` solicitação do Amazon S3 que usa a variante CRT signer e especifica uma data de assinatura futura.

```
val s3 = S3Client.fromEnvironment()

val unsignedRequest = GetObjectRequest {
    bucket = "foo"
    key = "bar"
}

val presignedRequest = s3.presignGetObject(unsignedRequest, signer = CrtAwsSigner) {
    signingDate = Instant.now() + 24.hours
    expiresAfter = 8.hours
}
```

A solicitação pré-assinada devolvida tem data de 24 horas e não é válida antes disso. Ele expira 8 horas depois disso.

## Pré-assinando solicitações POST e PUT
<a name="presign-requests-post-put"></a>

Muitas operações preassináveis exigem somente uma URL e devem ser executadas como solicitações HTTP GET. Algumas operações, no entanto, usam um corpo e devem ser executadas como uma solicitação HTTP POST ou HTTP PUT junto com cabeçalhos em alguns casos. A pré-assinatura dessas solicitações é idêntica à pré-assinatura de solicitações GET, mas invocar a solicitação pré-assinada é mais complicado.

Aqui está um exemplo de pré-assinatura de uma solicitação do S3: `PutObject`

```
val s3 = S3Client.fromEnvironment()

val unsignedRequest = PutObjectRequest {
    bucket = "foo"
    key = "bar"
}

val presignedRequest = s3.presignPutObject(unsignedRequest, 24.hours)
```

O retornado `HttpRequest` tem um valor de método de `HttpMethod.PUT` e inclui uma URL e cabeçalhos que devem ser incluídos na futura invocação da solicitação HTTP. Você pode passar essa solicitação para um chamador que pode executá-la em uma base de código ou ambiente de linguagem de programação diferente.

Depois de criar a solicitação POST ou PUT pré-assinada, use um cliente HTTP para invocar uma solicitação. A API para invocar uma URL de solicitação POST ou PUT depende do cliente HTTP usado. O exemplo a seguir usa um [cliente OkHttp HTTP](https://square.github.io/okhttp) e inclui um corpo que contém`Hello world`.

```
val putRequest = Request
    .Builder()
    .url(presignedRequest.url.toString())
    .apply {
        presignedRequest.headers.forEach { key, values ->
            header(key, values.joinToString(", "))
        }
    }
    .put("Hello world".toRequestBody())
    .build()

val response = okHttp.newCall(putRequest).execute()
```

## Operações que o SDK pode pré-assinar
<a name="presign-ops-supported"></a>

Atualmente, o SDK para Kotlin oferece suporte à pré-assinatura das seguintes operações de API que precisam ser chamadas com o método HTTP associado.


| AWS service (Serviço da AWS) | Operation | Método de extensão do SDK | Use o método HTTP | 
| --- | --- | --- | --- | 
| Amazon S3 | GetObject | [presignGetObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-get-object.html) |  HTTP GET  | 
| Amazon S3 | PutObject | [presignPutObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-put-object.html) |  HTTP PUT  | 
| Amazon S3 | UploadPart |  [presignUploadPart](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3.presigners/presign-upload-part.html)  |  HTTP PUT  | 
| AWS Security Token Service | GetCallerIdentity |  [presignGetCallerIdentidade](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/sts/aws.sdk.kotlin.services.sts.presigners/presign-get-caller-identity.html)  |  POSTAGEM HTTP  | 
| Amazon Polly | SynthesizeSpeech |  [presignSynthesizeSpeech](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/polly/aws.sdk.kotlin.services.polly.presigners/presign-synthesize-speech.html)  |  POSTAGEM HTTP  | 

# Solução de problemas FAQs
<a name="troubleshooting-faqs"></a>

Ao usar o AWS SDK para Kotlin em seus aplicativos, você pode encontrar alguns dos problemas listados neste tópico. Use as sugestões a seguir para ajudar a descobrir a causa raiz e resolver o erro.

## Como faço para corrigir problemas de “conexão fechada”?
<a name="ts-faq-connection-closed"></a>

Você pode encontrar problemas de “conexão fechada” como exceções, como um dos seguintes tipos: 
+ `IOException: unexpected end of stream on <URL>`
+ `EOFException: \n not found: limit=0`
+ `HttpException: AWS_ERROR_HTTP_CONNECTION_CLOSED: The connection has closed or is closing.; crtErrorCode=2058; HttpErrorCode(CONNECTION_CLOSED)`

Essas exceções indicam que uma conexão TCP do SDK com um serviço foi fechada ou redefinida inesperadamente. A conexão pode ter sido fechada pelo seu host, pelo AWS serviço ou por uma parte intermediária, como um gateway NAT, proxy ou balanceador de carga.

Esses tipos de exceções são repetidos automaticamente, mas ainda podem aparecer nos registros do SDK, dependendo da sua configuração de registro. Se a exceção for inserida em seu código, isso indica que a estratégia de repetição ativa esgotou seus limites configurados, como o máximo de tentativas ou o repositório de tokens de repetição. Consulte a [Tentativas novamente no AWS SDK para Kotlin](retries.md) seção deste guia para obter mais informações sobre estratégias de repetição. Consulte também [Por que as exceções são lançadas antes de atingir o máximo de tentativas?](#ts-faq-exceptions-before-max).

### Monitoramento de conexão inativa com o OkHttpEngine
<a name="ts-faq-connection-closed-okhttp"></a>

Se você estiver usando o `OkHttpEngine` e frequentemente encontrar `IOException: unexpected end of stream on <URL>` exceções, [considere ativar o monitoramento de conexões ociosas](http-client-config.md#http-idle-connection-monitoring). Esse recurso detecta quando servidores remotos têm conexões fechadas que ainda estão no pool de conexões, o que pode reduzir a ocorrência dessas exceções.

## Por que as exceções são lançadas antes de atingir o máximo de tentativas?
<a name="ts-faq-exceptions-before-max"></a>

Às vezes, você pode ver exceções que esperava que fossem repetidas, mas que, em vez disso, foram descartadas. Nessas situações, as etapas a seguir podem ajudar a resolver o problema.
+ **Verifique se a exceção pode ser repetida.** Algumas exceções não podem ser repetidas, como aquelas que indicam uma solicitação de serviço malformada, falta de permissões e recursos inexistentes, como exemplos. O SDK não repete automaticamente esses tipos de exceções. Para obter informações sobre como verificar exceções que podem ser repetidas, consulte. [Verifique se uma exceção pode ser repetida](retries.md#retries-check-exception-retryable)
+ **Verifique se a exceção está sendo inserida em seu código.** Algumas exceções aparecem nas mensagens de log como informações, mas na verdade não são incluídas em seu código. Por exemplo, exceções que podem ser repetidas, como erros de limitação, podem ser registradas, pois o SDK funciona automaticamente em vários ciclos. backoff-and-retry A invocação de uma operação do SDK gera uma exceção somente se não for tratada pelas configurações de repetição definidas.
+ **Verifique suas configurações de repetição definidas.** Consulte a [Tentativas novamente no AWS SDK para Kotlin](retries.md) seção deste guia para obter mais informações sobre estratégias e políticas de repetição. Certifique-se de que seu código esteja usando as configurações esperadas ou os padrões automáticos.
+ **Considere ajustar suas configurações de nova tentativa.** Depois de verificar os itens anteriores, mas o problema não ter sido resolvido, você pode considerar ajustar as configurações de nova tentativa.
  + **Aumente o número máximo de tentativas.** Por padrão, o número máximo de tentativas de uma operação é 3. Se você achar que isso não é suficiente e as exceções ainda estão ocorrendo na configuração padrão, considere aumentar a `retryStrategy.maxAttempts` propriedade na configuração do seu cliente. Consulte [Configurar o máximo de tentativas](retries.md#retires-max-attempts) para obter mais informações.
  + **Aumente as configurações de atraso.** Algumas exceções podem ser repetidas muito rapidamente antes que a condição subjacente tenha a chance de ser resolvida. Se você suspeitar que esse seja o caso, considere aumentar as `retryStrategy.delayProvider.maxBackoff` propriedades `retryStrategy.delayProvider.initialDelay` ou na configuração do seu cliente. Consulte [Configure atrasos e recuos](retries.md#retries-delays-backoff) para obter mais informações.
  + **Desative o modo disjuntor.** Por padrão, o SDK mantém um bucket de tokens para cada cliente de serviço. Quando o SDK tenta uma solicitação e ela falha com uma exceção que pode ser repetida, a contagem de tokens é diminuída; quando a solicitação é bem-sucedida, a contagem de tokens é incrementada. 

    Por padrão, se esse token bucket atingir 0 tokens restantes, o circuito será interrompido. Depois que o circuito é interrompido, o SDK desativa as novas tentativas e todas as solicitações atuais e subsequentes que falharem na primeira tentativa geram imediatamente uma exceção. O SDK reativa as novas tentativas após as tentativas iniciais bem-sucedidas retornarem capacidade suficiente ao token bucket. Esse comportamento é intencional e foi projetado para evitar novas tentativas durante interrupções e recuperação do serviço.

    Se você preferir que o SDK continue tentando novamente até o máximo de tentativas configuradas, considere desativar o modo disjuntor definindo a `retryStrategy.tokenBucket.useCircuitBreakerMode` propriedade como false na configuração do seu cliente. Com essa propriedade definida como false, o cliente SDK espera até que o token bucket atinja a capacidade suficiente, em vez de abandonar novas tentativas, o que pode levar a uma exceção quando houver 0 tokens restantes.

## Como faço para corrigir `NoSuchMethodError` ou NoClassDefFoundError?
<a name="ts-faq-nusuchmethod"></a>

Esses erros geralmente são causados por dependências ausentes ou conflitantes. Consulte [Como faço para resolver conflitos de dependência?](ts-faq-dep-conflict-resolution.md) para obter mais informações.

### Eu vejo um `NoClassDefFoundError` para `okhttp3/coroutines/ExecuteAsyncKt`
<a name="ts-faq-nusuchmethod-okhttp"></a>

Isso indica um problema de dependência OkHttp específico para. Consulte [Resolvendo conflitos de OkHttp versão em seu aplicativo](ts-faq-dep-conflict-resolution.md#okhttp-dep-conflicts) para obter mais informações.

# Como faço para resolver conflitos de dependência?
<a name="ts-faq-dep-conflict-resolution"></a>

Quando você usa o AWS SDK para Kotlin, ele precisa de determinadas dependências AWS e de terceiros para funcionar corretamente. Se essas dependências estiverem ausentes ou forem versões inesperadas em tempo de execução, você poderá ver erros como `NoSuchMethodError` ou`NoClassDefFoundError`. Esses problemas de dependência geralmente se dividem em dois grupos:
+ Conflitos de dependência do SDK/Smithy
+ Conflitos de dependência de terceiros

Ao criar seu aplicativo Kotlin, você provavelmente usará o Gradle para gerenciar dependências. Adicionar uma dependência em um cliente de serviço do SDK ao seu projeto inclui automaticamente todas as dependências relacionadas necessárias. No entanto, se seu aplicativo tiver outras dependências, elas poderão entrar em conflito com as exigidas pelo SDK. Por exemplo, o SDK depende OkHttp de um cliente HTTP popular que seu aplicativo também pode usar. Para ajudar você a identificar esses conflitos, o Gradle oferece uma tarefa útil que lista as dependências do seu projeto:

```
./gradlew dependencies
```

Quando você encontra conflitos de dependência, talvez seja necessário agir. Você pode especificar uma versão específica de uma dependência ou sombrear dependências em um namespace local. A resolução de dependências do Gradle é um tópico complexo discutido nas seções a seguir do Manual do usuário do *Gradle:*
+ [Entendendo a resolução de dependências](https://docs.gradle.org/current/userguide/dependency_resolution.html)
+ [Restrições de dependência e resolução de conflitos](https://docs.gradle.org/current/userguide/dependency_constraints_conflicts.html)
+ [Alinhando versões de dependência](https://docs.gradle.org/current/userguide/dependency_version_alignment.html)

## Gerenciando dependências do SDK e do Smithy em seu projeto
<a name="sdk-smithy-dep-conflicts"></a>

Ao usar o SDK, lembre-se de que seus módulos normalmente dependem de outros módulos do SDK com números de versão correspondentes. Por exemplo, `aws.sdk.kotlin:s3:1.2.3` depende de a`ws.sdk.kotlin:aws-http:1.2.3`, que depende de`aws.sdk.kotlin:aws-core:1.2.3`, e assim por diante.

Os módulos do SDK também usam versões específicas do módulo Smithy. Embora as versões do módulo Smithy não sejam sincronizadas com os números de versão do SDK, elas devem corresponder à versão esperada do SDK. Por exemplo, `aws.sdk.kotlin:s3:1.2.3` pode depender de`aws.smithy.kotlin:serde:1.1.1`, o que depende `aws.smithy.kotlin:runtime-core:1.1.1` e assim por diante.

Para evitar conflitos de dependência, atualize todas as dependências do SDK em conjunto e faça o mesmo com qualquer dependência explícita do Smithy. Considere usar nosso [catálogo de versões do Gradle](setup-create-project-file.md) para manter as versões sincronizadas e eliminar suposições no mapeamento entre as versões do SDK e do Smithy.

Lembre-se de que pequenas atualizações de versão nos SDK/Smithy módulos podem incluir alterações significativas, conforme descrito em nossa política de controle de [versão](https://github.com/awslabs/aws-sdk-kotlin/blob/main/VERSIONING.md#versioning-policy). Ao atualizar entre versões secundárias, analise cuidadosamente os registros de alterações e teste minuciosamente o comportamento do tempo de execução.

## Resolvendo conflitos de OkHttp versão em seu aplicativo
<a name="okhttp-dep-conflicts"></a>

[OkHttp](https://square.github.io/okhttp/)é um mecanismo HTTP popular que o SDK usa por padrão na JVM. Seu aplicativo pode incluir outras dependências ou estruturas que trazem uma versão diferente OkHttp . Isso pode causar um `NoClassDefFoundError` para classes no `okhttp3` namespace, como `okhttp/coroutines/ExecuteAsyncKt` ou. `okhttp3/ConnectionListener` Quando isso acontece, você geralmente deve escolher a versão mais recente para resolver conflitos. Para ajudar você a rastrear as fontes desses conflitos, o Gradle oferece uma tarefa útil. Você pode listar todas as dependências executando:

```
./gradlew dependencies
```

Por exemplo, se o SDK depende de OkHttp `5.0.0-alpha.14` e outra dependência, como Spring Boot, depende OkHttp `4.12.0`, então você deve usar o. `5.0.0-alpha.14 version` Você pode fazer isso com um `constraints` bloco no Gradle:

```
dependencies {
    constraints {
        implementation("com.squareup.okhttp3:okhttp:4.12.0")
    }
}
```

Como alternativa, se você precisar usar o OkHttp 4.x, o SDK fornecerá um. `OkHttp4Engine` Consulte a [documentação](https://github.com/smithy-lang/smithy-kotlin/tree/main/runtime/protocol/http-client-engines/http-client-engine-okhttp4) para obter informações sobre como configurar o Gradle e usá-lo `OkHttp4Engine` em seu código.

# Zombando no AWS SDK para Kotlin
<a name="mocking"></a>

Os desenvolvedores podem usar várias estruturas para realizar simulações em testes com o. AWS SDK para Kotlin Este tópico documenta configurações extras ou considerações especiais que algumas estruturas exigem.

## Zombar K
<a name="mockk-consideration"></a>

[Ao simular funções de extensão de todo o módulo usando o [MockK](https://mockk.io/), você precisa fazer uma configuração extra.](https://mockk.io/#extension-functions) No SDK para Kotlin, paginadores, garçons e presigners são exemplos de funções de extensão. Portanto, ao simular seu comportamento, você precisa de configuração extra.

Você deve ligar `mockkStatic("<MODULE_CLASS_NAME>")` antes de configurar suas simulações. Como regra geral, os nomes das classes do módulo são: 
+ **Paginadores**: `aws.sdk.kotlin.services.<service>.paginators.PaginatorsKt`
+ **Garçons:** `aws.sdk.kotlin.services.<service>.waiters.WaitersKt`
+ **Prescritores**: `aws.sdk.kotlin.services.<service>.presigners.PresignersKt`

Por exemplo, no teste a seguir, que inclui simulação `listBucketsPaginated` — uma função de extensão do paginador — adicionamos: `mockkStatic("aws.sdk.kotlin.services.s3.paginators.PaginatorsKt")`

```
    @Test
    fun testPaginatedListBuckets() = runTest {

        mockkStatic("aws.sdk.kotlin.services.s3.paginators.PaginatorsKt")
        val s3Client: S3Client = mockk()
        val s3BucketLister = S3BucketLister(s3Client)

        val expectedBuckets = listOf(
            Bucket { name = "bucket1" },
            Bucket { name = "bucket2" }
        )

        val response = ListBucketsResponse { buckets = expectedBuckets }
        coEvery { s3Client.listBucketsPaginated() } returns flowOf(response)

        val result = s3BucketLister.getAllBucketNames()

        assertEquals(listOf("bucket1", "bucket2"), result)
    }
```

Sem `mockkStatic` isso, você vê o seguinte erro:

```
Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
    at io.mockk.impl.recording.states.StubbingState.checkMissingCalls(StubbingState.kt:14)
    at io.mockk.impl.recording.states.StubbingState.recordingDone(StubbingState.kt:8)
    at io.mockk.impl.recording.CommonCallRecorder.done(CommonCallRecorder.kt:47)
    at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:63)
    at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
    at io.mockk.MockKDsl.internalCoEvery(API.kt:100)
    at io.mockk.MockKKt.coEvery(MockK.kt:174)
```

No caso de uma função de extensão presigner sem`mockkStatic`, você pode ver:

```
key is bound to the URI and must not be null
java.lang.IllegalArgumentException: key is bound to the URI and must not be null
    at aws.sdk.kotlin.services.s3.serde.GetObjectOperationSerializer.serialize(GetObjectOperationSerializer.kt:26)
    at aws.sdk.kotlin.services.s3.presigners.PresignersKt.presignGetObject(Presigners.kt:49)
    at aws.sdk.kotlin.services.s3.presigners.PresignersKt.presignGetObject$default(Presigners.kt:40)
    at aws.sdk.kotlin.services.s3.presigners.PresignersKt.presignGetObject-exY8QGI(Presigners.kt:30)
```

### Todos os exemplos de artefatos
<a name="mockk-full-example"></a>

#### Código em teste
<a name="mockk-example-code-under-test"></a>

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.paginators.listBucketsPaginated
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.runBlocking
import org.slf4j.Logger
import org.slf4j.LoggerFactory

fun main() {
    val logger: Logger = LoggerFactory.getLogger(::main.javaClass)

    // Create an S3Client
    S3Client { region = "us-east-1" }.use { s3Client ->
        // Create service instance
        val bucketLister = S3BucketLister(s3Client)
        // Since getAllBucketNames is a suspend function, you'll need to run it in a coroutine scope
        runBlocking {
            val bucketNames = bucketLister.getAllBucketNames()
            logger.info("Found buckets: $bucketNames")
        }
    }
}

class S3BucketLister(private val s3Client: S3Client) {
    suspend fun getAllBucketNames(): List<String> {
        return s3Client.listBucketsPaginated()
            .transform { response ->
                response.buckets?.forEach { bucket ->
                    emit(bucket.name ?: "")
                }
            }
            .filter { it.isNotEmpty() }
            .toList()
    }
}
```

#### Classe de teste
<a name="mockk-example-test-code"></a>

```
import aws.sdk.kotlin.services.s3.S3Client
import aws.sdk.kotlin.services.s3.model.Bucket
import aws.sdk.kotlin.services.s3.model.ListBucketsResponse
import aws.sdk.kotlin.services.s3.paginators.listBucketsPaginated
import io.mockk.coEvery
import io.mockk.mockk
import io.mockk.mockkStatic
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class S3BucketListerTest {

    @Test
    fun testPaginatedListBuckets() = runTest {

        mockkStatic("aws.sdk.kotlin.services.s3.paginators.PaginatorsKt")
        val s3Client: S3Client = mockk()
        val s3BucketLister = S3BucketLister(s3Client)

        val expectedBuckets = listOf(
            Bucket { name = "bucket1" },
            Bucket { name = "bucket2" }
        )

        val response = ListBucketsResponse { buckets = expectedBuckets }
        coEvery { s3Client.listBucketsPaginated() } returns flowOf(response)

        val result = s3BucketLister.getAllBucketNames()

        assertEquals(listOf("bucket1", "bucket2"), result)
    }
}
```

#### build.gradle.kts
<a name="mockk-example-gradle-build"></a>

```
plugins {
    kotlin("jvm") version "2.1.20"
    application
}

group = "org.example"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(platform(awssdk.bom))
    implementation(platform("org.apache.logging.log4j:log4j-bom:2.24.3"))

    implementation(awssdk.services.s3)
    implementation("org.apache.logging.log4j:log4j-slf4j2-impl")

    // Testing Dependencies
    testImplementation(platform("org.junit:junit-bom:5.11.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
    testImplementation("io.mockk:mockk:1.14.0")
}

tasks.test {
    useJUnitPlatform()
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

application {
    mainClass = "org.example.S3BucketService"
}
```

#### settings.gradle.kts
<a name="mockk-example-settings-build"></a>

```
plugins {
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
}
rootProject.name = "mockK-static"

dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }

    versionCatalogs {
        create("awssdk") {
            from("aws.sdk.kotlin:version-catalog:1.4.69")
        }
    }
}
```