

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

# の使用 AWS SDK for Java 2.x
<a name="using"></a>

この章では、 AWS SDK for Java 2.x を効果的に使用する方法について説明します。サービスクライアントの作成、リクエストの実行、レスポンスの処理、エラーの管理について説明します。この章では、同期プログラミングと非同期プログラミング、ページ分割された結果、リソースモニタリングのウェイター、パフォーマンスの最適化について説明します。

また、クライアントの再利用、トラブルシューティングガイダンス、Lambda 起動の最適化、HTTP/2 サポート、DNS 設定に関するベストプラクティスも記載しています。

**Contents**
+ [を使用した AWS のサービス リクエストの実行 AWS SDK for Java 2.x](work-witih-clients.md)
  + [サービスクライアントを使用したリクエストの実行](work-witih-clients.md#using-service-client)
    + [サービスクライアントを作成する](work-witih-clients.md#work-with-clients-create)
    + [デフォルトのクライアント設定](work-witih-clients.md#using-default-client)
    + [サービスクライアントを設定する](work-witih-clients.md#using-configure-service-clients)
    + [サービスクライアントを閉じる](work-witih-clients.md#using-closing-client)
  + [リクエストを発行する](work-witih-clients.md#using-making-requests)
    + [リクエストを使用してクライアント設定を上書きする](work-witih-clients.md#using-override-client-config-request)
  + [レスポンスを処理する](work-witih-clients.md#using-handling-responses)
+ [AWS SDK for Java 2.x を使用した非同期プログラミング](asynchronous.md)
  + [非同期クライアント API の使用](asynchronous.md#basics-async-non-streaming)
  + [非同期メソッドでのストリーミングの処理](asynchronous.md#basics-async-streaming)
  + [高度な非同期オプションを設定する](asynchronous.md#advanced-operations)
+ [を使用するためのベストプラクティス AWS SDK for Java 2.x](best-practices.md)
  + [API タイムアウトを設定してリクエストのハングを防止する](best-practices.md#bestpractice5)
  + [サービスクライアントを再利用してパフォーマンスを向上させる](best-practices.md#bestpractice1)
  + [未使用のサービスクライアントを閉じてリソースの漏洩を防ぐ](best-practices.md#bestpractice-close-client)
  + [入力ストリームを閉じて接続プールの枯渇を防ぐ](best-practices.md#bestpractice2)
  + [アプリケーションワークロードの HTTP パフォーマンスを最適化する](best-practices.md#bestpractice3)
  + [非同期クライアント用の OpenSSL で SSL パフォーマンスを向上させる](best-practices.md#bestpractice4)
  + [SDK メトリクスを使用してアプリケーションのパフォーマンスをモニタリングする](best-practices.md#bestpractice6)
+ [でのエラーの処理 AWS SDK for Java 2.x](handling-exceptions.md)
  + [非チェック例外を使用する理由](handling-exceptions.md#why-unchecked-exceptions)
  + [AwsServiceException (およびサブクラス)](handling-exceptions.md#sdkserviceexception-and-subclasses)
  + [SdkClientException](handling-exceptions.md#sdkclientexception)
  + [例外と再試行動作](handling-exceptions.md#retried-exceptions)
+ [AWS SDK for Java 2.x でページ分割された結果を使用する](pagination.md)
  + [同期ページ割り](pagination.md#synchronous-pagination)
    + [ページを反復処理する](pagination.md#iterate-pages)
    + [オブジェクトを反復処理する](pagination.md#iterate-objects)
      + [ストリーミングを使用する](pagination.md#use-a-stream)
      + [for-each ループを使用する](pagination.md#for-loop)
    + [手動のページ割り](pagination.md#manual-pagination)
  + [非同期ページ割り](pagination.md#asynchronous-pagination)
    + [テーブル名のページを反復処理する](pagination.md#iterate-pages-async)
      + [`Subscriber` を使用する](pagination.md#use-a-subscriber)
      + [`Consumer` を使用する](pagination.md#id1pagination)
    + [テーブル名を反復処理する](pagination.md#iterate-objects-async)
      + [`Subscriber` を使用する](pagination.md#id2)
      + [`Consumer` を使用する](pagination.md#for-loop-async)
    + [サードパーティーライブラリを使用する](pagination.md#use-third-party-library)
+ [でのウェーターの使用 AWS SDK for Java 2.x](waiters.md)
  + [前提条件](waiters.md#prerequisiteswaiters)
  + [ウェーターの使用](waiters.md#id1waiters)
    + [同期プログラミング](waiters.md#synchronous-programming)
    + [非同期プログラミング](waiters.md#asynchronous-programming)
  + [ウェイターを設定する](waiters.md#configuring-waiters)
    + [ウェーターを設定する](waiters.md#configure-a-waiter)
    + [特定のリクエストの設定をオーバーライドする](waiters.md#override-configuration-for-a-specific-request)
  + [コードの例](waiters.md#code-examples)
+ [トラブルシューティングに関するよくある質問](troubleshooting.md)
  + [「`java.net.SocketException`: Connection reset」または「server failed to complete the response」エラーを修正するにはどうすればよいですか?](troubleshooting.md#faq-socketexception)
  + [「connection timeout」を修正するにはどうすればよいですか?](troubleshooting.md#faq-connection-timeout)
  + [「`java.net.SocketTimeoutException`: Read timed out」を修正するにはどうすればよいですか?](troubleshooting.md#faq-socket-timeout)
  + [「Unable to execute HTTP request: Timeout waiting for connection from pool」エラーを修正するにはどうすればよいですか?](troubleshooting.md#faq-pool-timeout)
  + [`NoClassDefFoundError`、`NoSuchMethodError`、または `NoSuchFieldError` を修正するにはどうすればよいですか?](troubleshooting.md#faq-classpath-errors)
  + [「`SignatureDoesNotMatch`」エラーまたは「The request signature we calculated does not match the signature you provided」エラーを修正するにはどうすればよいですか?](troubleshooting.md#faq-signature-does-not-match-error)
  + [「`java.lang.IllegalStateException`: Connection pool shut down」エラーを修正するにはどうすればよいですか?](troubleshooting.md#faq-connection-pool-shutdown-exception)
  + [「Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain」を修正するにはどうすればよいですか?](troubleshooting.md#faq-credentials-provider-chain)
    + [一般的な原因と解決方法](troubleshooting.md#faq-cred-provider-chain-common-causes-and-solutions)
      + [認証情報設定を確認する](troubleshooting.md#faq-cred-provider-chain-check-config)
        + [Amazon EC2 インスタンスの場合](troubleshooting.md#faq-cred-check-ec2)
        + [コンテナ環境の場合](troubleshooting.md#faq-cred-check-container-env)
        + [ローカル開発の場合](troubleshooting.md#faq-cred-check-local-dev)
        + [ウェブ ID フェデレーションの場合](troubleshooting.md#faq-cred-check-web-id-federation)
      + [ネットワークまたはプロキシの接続の問題](troubleshooting.md#faq-credentials-provider-chain-network-issues)
+ [の SDK 起動時間を短縮する AWS Lambda](lambda-optimize-starttime.md)
  + [CRT ベースの AWS HTTP クライアントを使用する](lambda-optimize-starttime.md#lambda-quick-url)
  + [未使用の HTTP クライアント依存関係を削除する](lambda-optimize-starttime.md#lambda-quick-remove-deps)
  + [検索をショートカットするようにサービスクライアントを設定します。](lambda-optimize-starttime.md#lambda-quick-clients)
  + [Lambda 関数ハンドラーの外部で SDK クライアントを初期化する](lambda-optimize-starttime.md#lambda-quick-initialize)
  + [依存関係インジェクションを最小限に抑える](lambda-optimize-starttime.md#lambda-quick-di)
  + [Maven Archetype ターゲットを使用する AWS Lambda](lambda-optimize-starttime.md#lambda-quick-maven)
  + [Lambda SnapStart for Java を検討する](lambda-optimize-starttime.md#lambda-quick-snapstart)
  + [起動時間に影響するバージョン 2.x の変更点](lambda-optimize-starttime.md#example-client-configuration)
  + [その他のリソース](lambda-optimize-starttime.md#lambda-quick-resources)
+ [`ContentStreamProvider` で を実装する AWS SDK for Java 2.x](content-stream-provider.md)
  + [`mark()` および `reset()` を使用します。](content-stream-provider.md#csp-impl-mark-reset)
  + [`mark()` と `reset()` が利用できない場合にバッファリングを使用する](content-stream-provider.md#csp-impl-unsupported-streams)
  + [新しいストリームを作成する](content-stream-provider.md#csp-impl-new-stream)
+ [DNS 名参照用の JVM TTL を設定する](jvm-ttl-dns.md)
  + [JVM TTL を設定する方法](jvm-ttl-dns.md#how-to-set-the-jvm-ttl)
    + [オプション 1: アプリケーションでプログラムで設定する](jvm-ttl-dns.md#set-ttl-programmatically)
    + [オプション 2: java.security ファイルで設定する](jvm-ttl-dns.md#set-ttl-java-security-file)
    + [オプション 3: JDK システムプロパティのフォールバックを使用する (コマンドライン)](jvm-ttl-dns.md#set-ttl-system-property)
+ [AWS SDK for Java で HTTP/2 を使用する](http2.md)

# を使用した AWS のサービス リクエストの実行 AWS SDK for Java 2.x
<a name="work-witih-clients"></a>

## サービスクライアントを使用したリクエストの実行
<a name="using-service-client"></a>

[SDK のセットアップ](setup.md)のステップを完了し、[サービスクライアントの設定](configuring-service-clients.md)方法を理解したら、Amazon S3、Amazon DynamoDB、、 AWS Identity and Access Management Amazon EC2 などの AWS サービスにリクエストを行う準備が整います。

### サービスクライアントを作成する
<a name="work-with-clients-create"></a>

にリクエストを行うには AWS のサービス、まず静的ファクトリメソッド を使用して、そのサービスのサービスクライアントをインスタンス化する必要があります`builder()`。`builder()` メソッドは、サービスクライアントをカスタマイズできる `builder` オブジェクトを返します。fluent setter メソッドでは `builder` オブジェクトが返るため、利便性とコードの可読性を高めるためにメソッドの呼び出しをチェーンすることができます。必要なプロパティを設定した後、`build()` メソッドを呼び出してクライアントを作成します。

例として、以下のコードスニペットは、`Ec2Client` オブジェクトを Amazon EC2 のサービスクライアントとしてインスタンス化します。

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

**注記**  
SDK のサービスクライアントはスレッドセーフです。最高のパフォーマンスを得るには、長期間使用するオブジェクトとしてこれらを処理します。各クライアントには、クライアントがガーベージコレクションの対象になった場合にリリースされる独自の接続プールリソースを備えています。  
サービスクライアントオブジェクトはイミュータブルであるため、リクエストを実行する各サービスについて、または同じサービスにリクエストを実行するために異なる設定を使用する場合は、新しいクライアントを作成する必要があります。  
サービスクライアントビルダー`Region`で を指定することは、すべての AWS サービスに必須ではありませんが、アプリケーションで実行する API コールのリージョンを設定するのがベストプラクティスです。詳細については、「[AWS リージョンの選択](region-selection.md)」を参照してください。

### デフォルトのクライアント設定
<a name="using-default-client"></a>

このクライアントビルダーには、`create()` という名前の別のファクトリメソッドがあります。このメソッドでは、サービスクライアントがデフォルト設定で作成されます。[デフォルトのプロバイダーチェーン](credentials-chain.md)を使用して、認証情報と[デフォルトの AWS リージョン プロバイダーチェーン](region-selection.md#automatically-determine-the-aws-region-from-the-environment)をロードします。アプリケーションを実行している環境から認証情報またはリージョンを決定できない場合、`create` の呼び出しは失敗します。SDK が認証情報および使用するリージョンを決定する方法の詳細については、「[認証情報の使用](credentials.md)」および「[リージョンの選択](region-selection.md)」を参照してください。

例えば、以下のコードスニペットは、`DynamoDbClient` オブジェクトを Amazon DynamoDB のサービスクライアントとしてインスタンス化します。

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

### サービスクライアントを設定する
<a name="using-configure-service-clients"></a>

サービスクライアントの設定方法の詳細については、「[クライアントの外部設定](configuring-service-clients-ext.md)」および「[コードでのクライアント設定](configuring-service-clients-code.md)」を参照してください。

### サービスクライアントを閉じる
<a name="using-closing-client"></a>

ベストプラクティスとして、アプリケーションの存続期間中の複数の API サービス呼び出しにはサービスクライアントを使用する必要があります。ただし、サービスクライアントを 1 回だけ使用する必要がある場合や、サービスクライアントが不要になったら閉じます。

サービスクライアントが不要になったら、`close()` メソッドを呼び出してリソースを解放します。

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

サービスクライアントを 1 回だけ使用する必要がある場合は、`try`-with-resources ステートメントでサービスクライアントをリソースとしてインスタンス化できます。サービスクライアントは `[Autoclosable](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/AutoCloseable.html)` インターフェースを実装するため、JDK はステートメントの最後で自動的に `close()` メソッドを呼び出します。

以下の例は、サービスクライアントを使用して 1 回限りのコールを実行する方法を示しています。`StsClient` を呼び出す AWS Security Token Service は、アカウント ID を返した後で閉じられます。

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

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

## リクエストを発行する
<a name="using-making-requests"></a>

サービスクライアントを使用して、対応する にリクエストを行います AWS のサービス。

例えば、このコードスニペットは、`RunInstancesRequest` オブジェクトを作成して新しい 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);
```

SDK は、リクエストを作成してインスタンスに渡すのではなく、リクエストの作成に使用できる Fluent API を提供します。Fluent API を使用すると、Java Lambda 式を使用してリクエストを「インライン」で作成できます。

次の例では、[ビルダーを使用して](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/ec2/Ec2Client.html#runInstances(java.util.function.Consumer))リクエストを作成する `runInstances` メソッドのバージョンを使用して、前の例を書き換えています。

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

### リクエストを使用してクライアント設定を上書きする
<a name="using-override-client-config-request"></a>

サービスクライアントは変更不可能ですが、その設定の多くをリクエストレベルで上書きできます。リクエストを構築するときに、[AwsRequestOverrideConfiguration](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/AwsRequestOverrideConfiguration.html) インスタンスを指定して、設定を上書きできます。クライアント設定を上書きするために使用できるメソッドには、次のようなものがあります。
+ `apiCallAttemptTimeout`
+ `apiCallTimeout`
+ `credentialProvider`
+ `compressionConfiguration`
+ `putHeader`

リクエストでクライアント設定を上書きする例として、デフォルト設定を使用する次の S3 クライアントがあると想定してください。

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

大きなファイルをダウンロードし、ダウンロードが完了する前にリクエストがタイムアウトしないようにする必要があります。これを行うには、次のコードに示すように、1 つの `GetObject`リ クエストのみのタイムアウト値を増やします。

------
#### [ 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);
```

------

## レスポンスを処理する
<a name="using-handling-responses"></a>

SDK は、ほとんどのサービスオペレーションのレスポンスオブジェクトを返します。コードは、必要に応じてレスポンスオブジェクト内の情報を処理できます。

たとえば、次のコードスニペットは、前のリクエストの [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) オブジェクトで返された最初のインスタンス ID を出力します。

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

ただし、すべてのオペレーションがサービス固有のデータを含むレスポンスオブジェクトを返すわけではありません。このような状況では、HTTP レスポンスのステータスをクエリして、オペレーションが成功したかどうかを確認することができます。

たとえば、次のスニペットのコードは、HTTP レスポンスをチェックして、Amazon Simple Email Service の [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)) オペレーションが成功したかどうかを確認します。

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

# AWS SDK for Java 2.x を使用した非同期プログラミング
<a name="asynchronous"></a>

AWS SDK for Java 2.x は、少数のスレッドで同時実行を実現する、ノンブロッキング I/O をサポートした非同期クライアントを備えています。ただし、ノンブロッキング I/O の合計は保証されません。非同期クライアントは、認証情報の取得、[AWSSignature Version 4 (SigV4)](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) を使用したリクエスト署名、エンドポイント検出などのケースで、ブロック呼び出しを実行する場合があります。

同期メソッドは、クライアントがサービスからのレスポンスを受信するまでスレッドの実行をブロックします。非同期メソッドはすぐに応答を返し、レスポンスを待機せずに呼び出しスレッドに制御を戻します。

非同期メソッドはレスポンスが可能になる前に応答を返すため、準備ができたらレスポンスを得るための手段が必要になります。AWS SDK for Java の 2.x における非同期クライアントのメソッドでは、準備ができるとレスポンスにアクセスすることを許可する *CompletableFuture オブジェクト*が返されます。

## 非同期クライアント API の使用
<a name="basics-async-non-streaming"></a>

非同期クライアントメソッドの署名は同期メソッドと同じですが、非同期メソッドは、*将来の*非同期オペレーションの結果を含む [CompletableFuture](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/CompletableFuture.html) オブジェクトを返します。SDK の非同期メソッドの実行中にエラーがスローされた場合、エラーは `CompletionException` としてスローされます。

結果を取得するために使用できる方法の 1 つは、SDK メソッド呼び出しによって返された `CompletableFuture` に `whenComplete()` メソッドを連結させることです。`whenComplete()` メソッドは、非同期呼び出しの完了方法に応じて、結果または `CompletionException` タイプのスロー可能なオブジェクトを受け取ります。呼び出し元のコードに返される前に結果を処理またはチェックするために、アクションを `whenComplete()` に指定します。

SDK メソッドによって返されたオブジェクト以外のものを返す場合は、代わりに `handle()` メソッドを使用します。`handle()` メソッドは `whenComplete()` と同じパラメータを受け取りますが、結果を処理してオブジェクトを返すことができます。

非同期チェーンが完了するのを待ち、完了結果を取得するには、 `join()` メソッドを呼び出します。`Throwable` オブジェクトがチェーンで処理されなかった場合、 `join()` メソッドは元の例外をラップするチェックされていない `CompletionException` をスローします。元の例外には `CompletionException#getCause()` でアクセスします。`CompletableFuture#get()` メソッドを呼び出して、完了結果を取得することもできます。ただし、 `get()` メソッドはチェック例外をスローできます。

次の例は、DynamoDB 非同期クライアントの `listTables()` メソッドを使用する 2 つの異なる方法を示しています。`whenComplete()` に渡されたアクションは成功したレスポンスをログに記録するだけですが、`handle()` バージョンはテーブル名のリストを抽出してリストを返します。どちらの場合も、非同期チェーンでエラーが生成されるとエラーは再スローされるため、クライアントコードによって処理が可能です。

 **インポート** 

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

 **コード** 

------
#### [ 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;
                }
            });
    }
}
```

------

## 非同期メソッドでのストリーミングの処理
<a name="basics-async-streaming"></a>

ストリーミングコンテンツを扱う非同期メソッドでは、コンテンツを増分で渡すには [AsyncRequestBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html)、レスポンスを受信および処理するには [AsyncResponseTransformer](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncResponseTransformer.html) を渡す必要があります。

次の例では、非同期形式の `PutObject` オペレーションを使用して、ファイルを Amazon S3 に非同期的にアップロードします。

 **インポート** 

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

 **コード** 

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

次の例では、非同期形式の `GetObject` オペレーションを使用して、Amazon S3 からファイルを取得します。

 **インポート** 

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

 **コード** 

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

## 高度な非同期オプションを設定する
<a name="advanced-operations"></a>

AWS SDK for Java 2.x は、非同期イベント駆動型ネットワークアプリケーションフレームワークである [Netty](https://netty.io) を使用して I/O スレッドを処理します。AWS SDK for Java 2.x は Netty の背後に `ExecutorService` を作成し、HTTP クライアントリクエストから Netty クライアントに返された Future を完了します。この抽象化により、開発者がスレッドを停止またはスリープすることを選択した場合、アプリケーションが非同期プロセスをブレークするリスクが軽減されます。デフォルトでは、各非同期クライアントはプロセッサ数に基づいてスレッドプールを作成し、`ExecutorService` 内のキュー内のタスクを管理します。

非同期クライアントを構築する際に、`ExecutorService` の特定の JDK 実装を指定できます。次のスニペットは、固定のスレッド数を持つ `ExecutorService` を作成します。

 **コード** 

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

パフォーマンスを最適化するには、独自のスレッドプールエグゼキュターを管理し、クライアントの設定時に含めます。

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

# を使用するためのベストプラクティス AWS SDK for Java 2.x
<a name="best-practices"></a>

## API タイムアウトを設定してリクエストのハングを防止する
<a name="bestpractice5"></a>

SDK は、接続タイムアウトやソケットタイムアウトなど、一部のタイムアウトオプションにはデフォルト値を提供しますが、API コールタイムアウトや個々の API コール試行タイムアウトには[デフォルト値](https://github.com/aws/aws-sdk-java-v2/blob/a0c8a0af1fa572b16b5bd78f310594d642324156/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java#L134)を提供しません。個々の試行とリクエスト全体の両方にタイムアウトを設定するのがグッドプラクティスです。これにより、リクエストの完了までの時間が長くなるような一時的な問題や、致命的なネットワーク上の問題が発生した場合に、アプリケーションが最適な方法で迅速に失敗するようになります。

`[ClientOverrideConfiguration\$1apiCallAttemptTimeout](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html#apiCallAttemptTimeout())` と `[ClientOverrideConfiguration\$1apiCallTimeout](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html#apiCallTimeout())` を使用して、サービスクライアントが行うすべてのリクエストにタイムアウトを設定できます。

次の例は、カスタムタイムアウト値を使用する Amazon S3 クライアントの設定を示しています。

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

**`apiCallAttemptTimeout`**  
この設定では、1 回の HTTP 試行にかかる時間を設定します。この時間が経過すると API コールを再試行できます。

**`apiCallTimeout`**  
このプロパティの値は、すべての再試行を含む実行全体の時間を設定します。

サービスクライアントでこれらのタイムアウト値を設定する代わりに、[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()) と `[RequestOverrideConfiguration\$1apiCallAttemptTimeout()](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/RequestOverrideConfiguration.html#apiCallAttemptTimeout())` を使用して 1 つのリクエストを設定できます。

次の例では、カスタムタイムアウト値を使用して 1 つの `listBuckets` リクエストを設定します。

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

これらのプロパティを一緒に使用すると、すべての再試行に費やされる合計時間にハードリミットを設定します。また、低速なリクエストに対して、フェイルファストするよう、個々の HTTP リクエストを設定することもできます。

## サービスクライアントを再利用してパフォーマンスを向上させる
<a name="bestpractice1"></a>

各[サービスクライアント](work-witih-clients.md)は独自の HTTP 接続プールを維持します。プールにすでに存在する接続を新しいリクエストで再利用できるため、新しい接続を確立する時間を短縮できます。効果的に使用されていない接続プールが多すぎることによるオーバーヘッドを避けるため、クライアントの 1 つのインスタンスを共有することをおすすめします。すべてのサービスクライアントはすべてスレッドセーフです。

クライアントインスタンスを共有したくない場合は、クライアントが必要ないときにインスタンスで `close()` を呼び出してリソースを解放してください。

## 未使用のサービスクライアントを閉じてリソースの漏洩を防ぐ
<a name="bestpractice-close-client"></a>

不要になった場合は、[サービスクライアント](work-witih-clients.md)を閉じてスレッドなどのリソースをリリースします。クライアントインスタンスを共有したくない場合は、クライアントが必要ないときにインスタンスで `close()` を呼び出してリソースを解放してください。

## 入力ストリームを閉じて接続プールの枯渇を防ぐ
<a name="bestpractice2"></a>

`[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))` などのストリーミング操作では、`[ResponseInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/ResponseInputStream.html)` を直接操作する場合は、次を実行することをお勧めします。
+ できるだけ早く入力ストリームからすべてのデータを読み取ります。
+ できるだけ早く入力ストリームを閉じます。

このような推奨を行うのは、入力ストリームは HTTP 接続からのデータの直接ストリームであり、ストリームからのデータがすべて読み取られてストリームが閉じられるまで、基盤となる HTTP 接続を再利用できないためです。これらのルールに従わないと、開いているが未使用の HTTP 接続を大量に割り当てて、クライアントがリソースを使い果たす可能性があります。

## アプリケーションワークロードの HTTP パフォーマンスを最適化する
<a name="bestpractice3"></a>

SDK には、一般的なユースケースに適用される[デフォルト HTTP 設定](https://github.com/aws/aws-sdk-java-v2/blob/master/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java)セットが用意されています。お客様には、ユースケースに基づいてアプリケーションの HTTP 構成を調整することをお勧めします。

手始めに、SDK には[スマート設定のデフォルト](http-configuration.md#http-config-smart-defaults)機能が用意されています。この機能は、バージョン 2.17.102 で始めることで使用できます。ユースケースに応じて、適切な設定値が得られるモードを選択します。

## 非同期クライアント用の OpenSSL で SSL パフォーマンスを向上させる
<a name="bestpractice4"></a>

デフォルトでは、SDK の [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) は JDK のデフォルトの SSL 実装を `SslProvider` として使用します。テストの結果、OpenSSL は JDK のデフォルト実装よりもパフォーマンスが優れていることがわかりました。Netty コミュニティでは [OpenSSL の使用も推奨しています](https://netty.io/wiki/requirements-for-4.x.html#tls-with-openssl)。

OpenSSL を使用するには、依存関係に `netty-tcnative` を追加します。設定の詳細については、「[Netty プロジェクトのドキュメント](https://netty.io/wiki/forked-tomcat-native.html)」を参照してください。

プロジェクト用に `netty-tcnative` を設定すると、`NettyNioAsyncHttpClient` インスタンスは自動的に OpenSSL を選択します。または、次のスニペットに示すように、`NettyNioAsyncHttpClient`ビルダーを使用して明示的に `SslProvider` を設定することもできます。

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

## SDK メトリクスを使用してアプリケーションのパフォーマンスをモニタリングする
<a name="bestpractice6"></a>

SDK for Java は、アプリケーションのサービスクライアントの[メトリクスを収集](metrics.md)できます。これらのメトリクスを使用して、パフォーマンスの問題を特定したり、全体的な使用傾向を確認したり、返されたサービスクライアントの例外を確認したり、特定の問題を掘り下げて理解したりすることができます。

アプリケーションのパフォーマンスをより深く理解するために、メトリクスを収集して Amazon CloudWatch Logs を分析することをお勧めします。

# でのエラーの処理 AWS SDK for Java 2.x
<a name="handling-exceptions"></a>

SDK を使用して高品質のアプリケーションを構築するには、 が例外を AWS SDK for Java 2.x スローする方法とタイミングを理解することが重要です。以下のセクションでは、SDK によってスローされる例外のさまざまなケース、および例外の適切な処理方法について説明します。

## 非チェック例外を使用する理由
<a name="why-unchecked-exceptions"></a>

は、次の理由でチェック例外の代わりにランタイム (またはチェックされていない) 例外 AWS SDK for Java を使用します。
+ 懸念がない場合には例外ケースの処理を強制的に適用せずに (さらにコードを冗長にすることなく)、開発者がエラーを細かく制御できるようにするため。
+ サイズの大きいアプリケーションで、チェック例外に関連する拡張性の問題が発生するのを防ぐため。

一般的に、チェック例外は小規模なアプリケーションでは役立ちますが、アプリケーションのサイズが大きくなり、複雑化すると、チェック例外が問題となる場合があります。

## AwsServiceException (およびサブクラス)
<a name="sdkserviceexception-and-subclasses"></a>

 [AwsServiceException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsServiceException.html) は、 の使用時に発生する最も一般的な例外です AWS SDK for Java。 `AwsServiceException`は、より一般的な [SdkServiceException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkServiceException.html) のサブクラスです。 `AwsServiceException`は、 からのエラーレスポンスを表します AWS のサービス。たとえば、存在しない Amazon EC2 インスタンスを終了しようとすると、 Amazon EC2 はエラーレスポンスを返し、そのエラーレスポンスのすべての詳細がスロー`AwsServiceException`される に含まれます。

が発生すると`AwsServiceException`、リクエストは に正常に送信されました AWS のサービス が、正常に処理できなかったことがわかります。これは、リクエストのパラメータに含まれるエラーまたはサービス側の問題が原因です。

 `AwsServiceException` では次のような情報がわかります。
+ 返された HTTP ステータスコード
+ 返された AWS エラーコード
+ [AwsErrorDetails](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsErrorDetails.html) クラスのサービスからの詳細なエラーメッセージ。
+  AWS 失敗したリクエストのリクエスト ID

ほとんどの場合、`AwsServiceException` のサービス固有のサブクラスがスローされ、開発者はキャッチブロックを通じてエラーケースの処理を細かく制御できます。[AwsServiceException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsServiceException.html) の Java SDK API リファレンスには、多数の `AwsServiceException` サブクラスが表示されています。サブクラスリンクを使用してドリルダウンすると、サービスによってスローされた詳細な例外を確認できます。

たとえば、以下の SDK API リファレンスへのリンクは、いくつかの一般的な AWS のサービスの例外階層を示しています。各ページに表示されるサブクラスのリストには、コードがキャッチできる特定の例外が表示されます。
+ [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)

例外の詳細については、[AwsErrorDetails](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/exception/AwsErrorDetails.html) オブジェクトで `errorCode` を調べてください。`errorCode` 値を使用して、サービスガイド API の情報を検索できます。たとえば、`S3Exception` がキャッチされ、`AwsErrorDetails#errorCode()` 値が `InvalidRequest` の場合、Amazon S3 API リファレンスの[エラーコードのリスト](https://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html#ErrorCodeList)を使用して詳細を確認してください。

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

 [SdkClientException](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/exception/SdkClientException.html) は、 へのリクエストの送信中またはレスポンスの解析 AWS 中に、Java クライアントコード内で問題が発生したことを示します AWS。`SdkClientException` は通常、 よりも深刻であり`SdkServiceException`、クライアントが のサービスコールを実行できない大きな問題を示します AWS 。たとえば、いずれかのクライアントで オペレーションを呼び出そうとすると、ネットワーク接続が利用`SdkClientException`できない場合、 は を AWS SDK for Java スローします。

## 例外と再試行動作
<a name="retried-exceptions"></a>

SDK for Java は、いくつかの[クライアント側の例外](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)と AWS のサービス レスポンスから受信した [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)のリクエストを再試行します。これらのエラーは、サービスクライアントがデフォルトで使用するレガシー `RetryMode` の一部として処理されます。`[RetryMode](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/RetryMode.html)` の Java API リファレンスには、モードを設定するさまざまな方法が記載されています。

自動再試行をトリガーする例外と HTTP ステータスコードをカスタマイズするには、`[RetryOnExceptionsCondition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/conditions/RetryOnExceptionsCondition.html)`、`[RetryOnStatusCodeCondition](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/awscore/retry/conditions/RetryOnErrorCodeCondition.html)` インスタンスを追加する `[RetryPolicy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/retry/RetryPolicy.html)` をサービスクライアントに設定します。

# AWS SDK for Java 2.x でページ分割された結果を使用する
<a name="pagination"></a>

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

**注記**  
これらのコードスニペットは、ユーザーが [SDK の使用の基本](using.md)を理解し、[シングルサインオンアクセス](get-started-auth.md#setup-credentials)で環境を設定していることを前提としています。

## 同期ページ割り
<a name="synchronous-pagination"></a>

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

### ページを反復処理する
<a name="iterate-pages"></a>

最初の例は、[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) インスタンスである `listRes` ページネーターオブジェクトを使用して、`stream` メソッドですべてのレスポンスページをイテレーションする例です。コードはレスポンスページをストリーミングし、レスポンスストリームを`[S3Object](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/S3Object.html)`コンテンツのストリームに変換して、 Amazon S3 オブジェクトのコンテンツを処理します。

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

#### インポート
<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()));
```

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L112) で完全な例をご覧ください。

### オブジェクトを反復処理する
<a name="iterate-objects"></a>

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

#### ストリーミングを使用する
<a name="use-a-stream"></a>

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

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

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L127) で完全な例をご覧ください。

#### for-each ループを使用する
<a name="for-loop"></a>

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

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

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L133) で完全な例をご覧ください。

### 手動のページ割り
<a name="manual-pagination"></a>

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

```
        ListObjectsV2Request listObjectsReqManual = ListObjectsV2Request.builder()
            .bucket(bucketName)
            .maxKeys(1)
            .build();

        boolean done = false;
        while (!done) {
            ListObjectsV2Response listObjResponse = s3.listObjectsV2(listObjectsReqManual);
            for (S3Object content : listObjResponse.contents()) {
                System.out.println(content.key());
            }

            if (listObjResponse.nextContinuationToken() == null) {
                done = true;
            }

            listObjectsReqManual = listObjectsReqManual.toBuilder()
                .continuationToken(listObjResponse.nextContinuationToken())
                .build();
        }
```

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/s3/src/main/java/com/example/s3/S3ObjectOperations.java#L90) で完全な例をご覧ください。

## 非同期ページ割り
<a name="asynchronous-pagination"></a>

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

### テーブル名のページを反復処理する
<a name="iterate-pages-async"></a>

次の 2 つの例では、非同期の DynamoDB クライアントを使用して `listTablesPaginator` メソッドを呼び出し、[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` には 2 つのインターフェースが実装されており、レスポンスを処理するための多くのオプションが用意されています。各インターフェースのメソッドを見ていきます。

#### `Subscriber` を使用する
<a name="use-a-subscriber"></a>

次のコード例は、`ListTablesPublisher` で実装された `org.reactivestreams.Publisher` インターフェイスを使用してページ分割された結果を処理する方法を示しています。リアクティブなストリームのモデルの詳細については、「[Reactive Streams GitHub repo](https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.2/README.md)」を参照してください。

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

##### インポート
<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;
```

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

```
        // Creates a default client with credentials and region loaded from the
        // environment.
        final DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create();

        ListTablesRequest listTablesRequest = ListTablesRequest.builder().limit(3).build();
        ListTablesPublisher publisher = asyncClient.listTablesPaginator(listTablesRequest);
```

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

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

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

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

```
        // A Subscription represents a one-to-one life-cycle of a Subscriber subscribing
        // to a Publisher.
        publisher.subscribe(new Subscriber<ListTablesResponse>() {
            // Maintain a reference to the subscription object, which is required to request
            // data from the publisher.
            private Subscription subscription;

            @Override
            public void onSubscribe(Subscription s) {
                subscription = s;
                // Request method should be called to demand data. Here we request a single
                // page.
                subscription.request(1);
            }

            @Override
            public void onNext(ListTablesResponse response) {
                response.tableNames().forEach(System.out::println);
                // After you process the current page, call the request method to signal that
                // you are ready for next page.
                subscription.request(1);
            }

            @Override
            public void onError(Throwable t) {
                // Called when an error has occurred while processing the requests.
            }

            @Override
            public void onComplete() {
                // This indicates all the results are delivered and there are no more pages
                // left.
            }
        });
```

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L83) で完全な例をご覧ください。

#### `Consumer` を使用する
<a name="id1pagination"></a>

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

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

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

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L96) で完全な例をご覧ください。

### テーブル名を反復処理する
<a name="iterate-objects-async"></a>

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

#### `Subscriber` を使用する
<a name="id2"></a>

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

```
        // Create a default client with credentials and region loaded from the
        // environment.
        final DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create();

        ListTablesRequest listTablesRequest = ListTablesRequest.builder().limit(3).build();
        ListTablesPublisher listTablesPublisher = asyncClient.listTablesPaginator(listTablesRequest);
        SdkPublisher<String> publisher = listTablesPublisher.tableNames();
```

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

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

```
        // Use a Subscriber.
        publisher.subscribe(new Subscriber<String>() {
            private Subscription subscription;

            @Override
            public void onSubscribe(Subscription s) {
                subscription = s;
                subscription.request(1);
            }

            @Override
            public void onNext(String tableName) {
                System.out.println(tableName);
                subscription.request(1);
            }

            @Override
            public void onError(Throwable t) {
            }

            @Override
            public void onComplete() {
            }
        });
```

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L147) で完全な例をご覧ください。

#### `Consumer` を使用する
<a name="for-loop-async"></a>

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

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

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L161) で完全な例をご覧ください。

### サードパーティーライブラリを使用する
<a name="use-third-party-library"></a>

カスタムの受信者を実装せずに、その他のサードパーティーのライブラリを使用することができます。この例では、RxJava の使用を例に挙げていますが、リアクティブなストリームのインターフェイスを実装するライブラリを使用することもできます。上記ライブラリの詳細については、「[RxJava wiki page on GitHub](https://github.com/ReactiveX/RxJava/wiki)」を参照してください。

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

 **POM エントリ** 

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

 **Code** 

```
        DynamoDbAsyncClient asyncClient = DynamoDbAsyncClient.create();
        ListTablesPublisher publisher = asyncClient.listTablesPaginator(ListTablesRequest.builder()
                .build());

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

[GitHub](https://github.com/awsdocs/aws-doc-sdk-examples/blob/f807d60010caf3d14fe4cd0801b842fb8e9511ca/javav2/example_code/dynamodbasync/src/main/java/com/example/dynamodbasync/AsyncPagination.java#L198) で完全な例をご覧ください。

# でのウェーターの使用 AWS SDK for Java 2.x
<a name="waiters"></a>

 AWS SDK for Java 2.x のウェーターユーティリティを使用すると、 AWS リソースに対してオペレーションを実行する前に、リソースが指定された状態であることを検証できます。

*ウェーター*は、目的の状態に達するまで (または AWS リソースが目的の状態に到達しないと判断されるまで）、 DynamoDB テーブルや Amazon S3 バケットなどのリソースをポーリングするために使用される抽象化です。面倒でエラーが発生しやすい AWS リソースを継続的にポーリングするロジックを記述する代わりに、ウェーターを使用してリソースをポーリングし、リソースの準備ができた後もコードを実行し続けることができます。

## 前提条件
<a name="prerequisiteswaiters"></a>

でプロジェクトでウェーターを使用する前に AWS SDK for Java、[AWS SDK for Java 「2.x のセットアップ](setup.md)」のステップを完了する必要があります。

 AWS SDK for Javaのバージョン `2.15.0` 以降を使用するように、プロジェクトの依存関係を (例: `pom.xml` または `build.gradle` ファイルで) 設定する必要もあります。

例えば、次のようになります。

```
<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>
```

## ウェーターの使用
<a name="id1waiters"></a>

ウェイターオブジェクトをインスタンス化するには、最初にサービスクライアントを作成します。サービスクライアントの `waiter()` メソッドをウェイターオブジェクトの値として設定します。ウェイターインスタンスが存在するようになったら、適切なコードを実行するようにその応答オプションを設定します。

### 同期プログラミング
<a name="synchronous-programming"></a>

次のコードスニペットは、 DynamoDB テーブルが存在し、**ACTIVE** 状態になるまで待機する方法を示しています。

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

### 非同期プログラミング
<a name="asynchronous-programming"></a>

次のコードスニペットは、 DynamoDB テーブルが存在しないまで待機する方法を示しています。

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

## ウェイターを設定する
<a name="configuring-waiters"></a>

ビルダーで `overrideConfiguration()` を使用して、ウェイターの設定をカスタマイズできます。一部の操作では、リクエストを実行する際にカスタム設定を適用できます。

### ウェーターを設定する
<a name="configure-a-waiter"></a>

次のコードスニペットは、ウェイターの設定を上書きする方法を示しています。

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

### 特定のリクエストの設定をオーバーライドする
<a name="override-configuration-for-a-specific-request"></a>

次のコードスニペットは、リクエストごとにウェイターの設定を上書きする方法を示しています。すべての操作でカスタマイズ可能な設定があるわけではないことに注意してください。

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

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

## コードの例
<a name="code-examples"></a>

でウェーターを使用する完全な例については DynamoDB、 AWS 「 Code Examples Repository」の[CreateTable.java](https://github.com/awsdocs/aws-doc-sdk-examples/blob/869b7ddbc7c8f66c7c45acd5b813429aff37003e/javav2/example_code/dynamodb/src/main/java/com/example/dynamodb/CreateTable.java)」を参照してください。

でウェーターを使用する完全な例については Amazon S3、 AWS 「 Code Examples Repository」の[S3BucketOps.java](https://github.com/awsdocs/aws-doc-sdk-examples/blob/869b7ddbc7c8f66c7c45acd5b813429aff37003e/javav2/example_code/s3/src/main/java/com/example/s3/S3BucketOps.java)」を参照してください。

# トラブルシューティングに関するよくある質問
<a name="troubleshooting"></a>

 AWS SDK for Java 2.x アプリケーションで を使用すると、このトピックに記載されているランタイムエラーが発生する可能性があります。根本原因を見つけてエラーを解決するには、このガイドの提案を参考にしてください。

## 「`java.net.SocketException`: Connection reset」または「server failed to complete the response」エラーを修正するにはどうすればよいですか?
<a name="faq-socketexception"></a>

接続リセットエラーは、リクエストが完了する前にホスト AWS のサービス、、または仲介者 (NAT ゲートウェイ、プロキシ、ロードバランサーなど) が接続を閉じたことを示します。多くの原因があるため、ソリューションを見つけるには、接続が閉じられた理由を知る必要があります。通常、以下の理由によって接続が閉じられます。
+ **接続が非アクティブ。 **これはストリーミングオペレーションでよく見られる動作です。一定期間データの送受信が行われないため、仲介者が接続がデッドであると判断して切断してしまうことがあります。これを防ぐには、アプリケーションがデータをアクティブにダウンロードまたはアップロードしていることを確認してください。
+ **HTTP または SDK クライアントを閉じた。**使用中はリソースを閉じないでください。
+ **プロキシの設定ミス。**設定したプロキシをバイパスして、問題が修正されるかどうかを確認してください。これにより問題が修正された場合、プロキシが何らかの理由で接続を閉じています。特定のプロキシを調べて、接続を閉じている理由を特定します。

問題を特定できない場合は、影響を受けた接続の tcpdump をネットワークのクライアントエッジで実行してみてください (たとえば、制御するプロキシの後など）。

 AWS エンドポイントが `TCP RST` (リセット) を送信していることがわかった場合は[、影響を受けるサービスに連絡して](https://aws.amazon.com/contact-us/)、リセットが発生している理由を判断できるかどうかを確認してください。問題が発生したときのリクエスト ID とタイムスタンプを提示できるように準備してください。 AWS サポートチームは、アプリケーションが送受信しているバイト数とタイミングを正確に示す[ワイヤログ](logging-slf4j.md#sdk-java-logging-verbose)からメリットを得ることもできます。

## 「connection timeout」を修正するにはどうすればよいですか?
<a name="faq-connection-timeout"></a>

接続タイムアウトエラーは、ホスト、 AWS のサービス、または仲介者 (NAT ゲートウェイ、プロキシ、ロードバランサーなど) が、設定された接続タイムアウト内にサーバーとの新しい接続を確立できなかったことを示します。以下の項目は、この問題の一般的な原因です。
+ **設定された接続タイムアウト値が低すぎる。**デフォルトでは、 AWS SDK for Java 2.xでの接続タイムアウトは 2 秒です。接続タイムアウト値を低く設定しすぎると、このエラーが発生する可能性があります。推奨される接続タイムアウトは、リージョン内呼び出しのみを行う場合は 1 秒、クロスリージョンリクエストを行う場合は 3 秒です。
+ **プロキシの設定ミス。**設定したプロキシをバイパスして、問題が修正されるかどうかを確認してください。これにより問題が解決した場合、プロキシが接続タイムアウトの原因です。特定のプロキシを調べて、問題が発生した理由を判断します。

問題を特定できない場合は、影響を受けた接続の tcpdump をネットワークのクライアントエッジで実行して (たとえば、制御するプロキシの後など）、ネットワークの問題を調査します。

## 「`java.net.SocketTimeoutException`: Read timed out」を修正するにはどうすればよいですか?
<a name="faq-socket-timeout"></a>

読み取りタイムアウトエラーは、JVM が基盤となるオペレーティングシステムからデータを読み取ろうとしたものの、SDK を介して設定された時間内にデータが返されなかったことを示します。このエラーは、オペレーティングシステム、 AWS のサービス、または仲介者 (NAT ゲートウェイ、プロキシ、ロードバランサーなど) が JVM が想定する時間内にデータを送信できない場合に発生する可能性があります。多くの原因があるため、ソリューションを見つけるには、データが返されない理由を知る必要があります。

影響を受けた接続の tcpdump をネットワークのクライアントエッジで実行してみてください (たとえば、制御するプロキシの後など）。

 AWS エンドポイントが `TCP RST` を送信 (リセット) [していることがわかった場合は、影響を受ける サービスにお問い合わせください](https://aws.amazon.com/contact-us/)。問題が発生したときのリクエスト ID とタイムスタンプを提示できるように準備してください。 AWS サポートチームは、アプリケーションが送受信しているバイト数とタイミングを正確に示す[ワイヤログ](logging-slf4j.md#sdk-java-logging-verbose)からメリットを得ることもできます。

## 「Unable to execute HTTP request: Timeout waiting for connection from pool」エラーを修正するにはどうすればよいですか?
<a name="faq-pool-timeout"></a>

このエラーは、リクエストが指定された最大時間内にプールから接続を取得できないことを示します。問題をトラブルシューティングするには、[SDK クライアント側のメトリクスを有効にして](metrics.md)、Amazon CloudWatch にメトリクスを公開することをお勧めします。HTTP メトリクスは、根本原因を絞り込むのに役立ちます。以下の項目は、このエラーの一般的な原因です。
+ **接続リーク。**これを調査するには、`LeasedConcurrency`、`AvailableConcurrency`、および `MaxConcurrency` メトリクスを確認します。`MaxConcurrency` に達するまで `LeasedConcurrency` が増加するものの、その後減少しない場合、接続リークが発生している可能性があります。リークの一般的な原因は、S3 `getObject` メソッドなどのストリーミングオペレーションが閉じられていないことです。アプリケーションで、できるだけ早く入力ストリームからすべてのデータを読み取り、[その後の入力ストリームを閉じる](best-practices.md#bestpractice2)ことをお勧めします。次の図は、接続リークの SDK メトリクスの例を示しています。  
![\[接続リークの可能性を示す CloudWatch メトリクスのスクリーンショット。\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/images/JavaDevGuide-connection-leak-metrics-chart.png)
+ **接続プールの不足。 **これは、リクエストレートが高すぎて、設定された接続プールのサイズがリクエストの需要を満たせない場合に発生する可能性があります。デフォルトの接続プールサイズは 50 で、プール内の接続が最大に達すると、HTTP クライアントは接続が利用可能になるまで受信リクエストをキューに入れます。次の図は、接続プールが不足した場合の SDK メトリクスの例を示しています。  
![\[接続プールが不足した場合の CloudWatch メトリクスの例を示すスクリーンショット。\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/images/JavaDevGuide-connection-pool-starvation-chart.png)

  この問題を軽減するには、次のいずれかのアクションを実行することを検討してください。
  + 接続プールのサイズを大きくする。
  + 取得タイムアウトを長くする。
  + リクエストレートを低くする。

  接続の最大数を増やすことで、クライアントスループットを向上させることができます (ネットワークインターフェイスが既に完全に使用されている場合を除く）。ただし、最終的には、プロセスで使用されるファイル記述子の数に対するオペレーティングシステムの制限に達する可能性があります。ネットワークインターフェイスを既に完全に使用している場合、または接続数をこれ以上増やすことができない場合は、取得タイムアウトを長くしてみてください。これにより、タイムアウトする前にリクエストが接続を取得する時間を追加できます。接続が解放されない場合でも、後続のリクエストはタイムアウトします。

  最初の 2 つのメカニズムを使用して問題を解決できない場合は、次のオプションでリクエストレートを低くします。
  + 大量のトラフィックバーストによってクライアントが過負荷にならないように、リクエストを円滑化する。
  + を呼び出す方が効率的です AWS のサービス。
  + リクエストを送信するホストの数を増やす。
+ **I/O スレッドがビジー状態。**この原因は、[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) で非同期 SDK クライアントを使用している場合にのみ該当します。`AvailableConcurrency` メトリクスが低くなく、接続がプールで使用可能であることを示しているものの `ConcurrencyAcquireDuration` が高い場合は、I/O スレッドがリクエストを処理できていない可能性があります。[future 完了エグゼキュター](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.html#FUTURE_COMPLETION_EXECUTOR)として `Runnable:run` を渡したり、レスポンスの future 完了チェーン内で時間のかかる処理を実行したりしないよう注意してください。こうした処理は I/O スレッドをブロックする可能性があります。そうでない場合は、 `[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))` メソッドを使用して I/O スレッドの数を増やすことを検討してください。参考までに、`NettyNioAsyncHttpClient` インスタンスの I/O スレッドのデフォルト数は、ホストの CPU コア数の 2 倍です。
+ **TLS ハンドシェイクのレイテンシーが高い。**`AvailableConcurrency` メトリクスが 0 に近く、`LeasedConcurrency` が `MaxConcurrency` より小さい場合は、TLS ハンドシェイクのレイテンシーが高いことが原因である可能性があります。次の図は、TLS ハンドシェイクのレイテンシーが高い場合の SDK メトリクスの例を示しています。  
![\[TLS ハンドシェイクのレイテンシーが高い可能性を示す CloudWatch メトリクスのスクリーンショット。\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/images/JavaDevGuide-high-tls-latency-chart.png)

  CRT に基づいていない Java SDK が提供する HTTP クライアントの場合は、[TLS ログ](security-java-tls.md)を有効にして TLS の問題をトラブルシューティングしてみてください。 AWS CRT ベースの HTTP クライアントの場合は、[AWS CRT ログ](logging-slf4j.md#sdk-java-logging-verbose)を有効にしてみてください。 AWS エンドポイントが TLS ハンドシェイクの実行に時間がかかると思われる場合は、[影響を受ける サービスにお問い合わせください](https://aws.amazon.com/contact-us/)。

## `NoClassDefFoundError`、`NoSuchMethodError`、または `NoSuchFieldError` を修正するにはどうすればよいですか?
<a name="faq-classpath-errors"></a>

`NoClassDefFoundError` は、ランタイムにクラスをロードできなかったことを示しています。このエラーの最も一般的な原因は 2 つあります。
+ JAR が欠落しているか、クラスパスに間違ったバージョンの JAR があるため、 クラスパスにクラスが存在しない。
+ 静的イニシャライザが例外をスローしたため、 クラスをロードできなかった。

同様に、 `NoSuchMethodError` と `NoSuchFieldError` は通常、JAR バージョンが一致しないために発生します。次の手順を実行することをお勧めします。

1. **依存関係をチェック**して、*すべての SDK jar に同じバージョン*を使用していることを確認します。クラス、メソッド、またはフィールドが見つからない最も一般的な理由は、新しいクライアントバージョンにアップグレードしても、古い「共有」 SDK 依存関係バージョンを引き続き使用している場合です。新しいクライアントバージョンは、新しい「共有」 SDK 依存関係にしか存在しないクラスを使用しようとする場合があります。`mvn dependency:tree` または `gradle dependencies` (Gradle の場合) を実行して、SDK ライブラリのバージョンがすべて一致することを確認します。将来的にこの問題を完全に回避するには、[BOM (部品表)](setup-project-maven.md#sdk-as-dependency) を使用して SDK モジュールバージョンを管理することをお勧めします。

   次は、SDK バージョンが混在している例を示しています。

   ```
   [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
   ```

   `dynamodb` のバージョンは 2.20.00、`aws-core` のバージョンは 2.13.19 です。`aws-core` アーティファクトバージョンも 2.20.00 である必要があります。

1. **ログの早い段階でステートメントをチェック**して、静的初期化の失敗が原因でクラスがロードに失敗したかどうかを確認します。クラスが初めてロードに失敗すると、クラスをロードできない*理由*を示す、より便利な別の例外がスローされる場合があります。この役立つ可能性のある例外は 1 回だけ発生し、後のログステートメントではクラスが見つからないことのみが報告されます。

1. **デプロイプロセスをチェック**して、アプリケーションと一緒に必要な JAR ファイルがデプロイされていることを確認します。正しいバージョンで構築しているものの、アプリケーションのクラスパスを作成するプロセスで、必要な依存関係が除外されている可能性があります。

## 「`SignatureDoesNotMatch`」エラーまたは「The request signature we calculated does not match the signature you provided」エラーを修正するにはどうすればよいですか?
<a name="faq-signature-does-not-match-error"></a>

`SignatureDoesNotMatch` エラーは、 によって生成された署名 AWS SDK for Java と によって生成された署名が一致し AWS のサービス ないことを示します。以下の項目は、潜在的な原因です。
+ プロキシまたは仲介者がリクエストを変更している。たとえば、プロキシまたはロードバランサーは、SDK によって署名されたヘッダー、パス、またはクエリ文字列を変更する場合があります。
+ サービスおよび SDK はそれぞれ、署名する文字列を生成するときにリクエストをエンコードする方法が異なります。

この問題をデバッグするには、SDK の[デバッグログを有効にする](logging-slf4j.md#sdk-debug-level-logging)ことをお勧めします。エラーを再現し、SDK が生成した正規リクエストを見つけます。ログでは、正規リクエストには `AWS4 Canonical Request: ...` というラベルが付けられ、署名する文字列には `AWS4 String to sign: ...` というラベルが付けられます。

たとえば、本番環境でのみ再現可能であるためにデバッグを有効にできない場合は、エラーが発生したときにリクエストに関する情報をログに記録するロジックをアプリケーションに追加します。その後、その情報を使用して、デバッグログを有効にした統合テストで本番環境外でエラーを再現できます。

署名する正規リクエストと文字列を収集した後、[AWS 署名バージョン 4 の仕様](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)と比較して、SDK が署名する文字列を生成した方法に問題がないかどうかを確認します。問題があると思われる場合は、 AWS SDK for Javaへの [GitHub バグレポート](https://github.com/aws/aws-sdk-java-v2/issues/new/choose)を作成できます。

何も問題が表示されない場合は、SDK の 文字列と 文字列を比較して、一部の が失敗レスポンス (Amazon S3 など) の一部として を AWS のサービス 返すことを示すことができます。これが利用できない場合は、[影響を受けるサービスに問い合わせて](https://aws.amazon.com/contact-us/)、生成された正規リクエストと署名文字列を確認して比較する必要があります。比較することで、リクエストを変更した可能性のある仲介者や、サービスとクライアント間のエンコードの違いを特定できます。

リクエストの署名の詳細については、「 AWS Identity and Access Management ユーザーガイド[」の AWS 「 API リクエストの署名](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-signing.html)」を参照してください。

**Example 正規リクエスト**  

```
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 署名文字列**  

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

## 「`java.lang.IllegalStateException`: Connection pool shut down」エラーを修正するにはどうすればよいですか?
<a name="faq-connection-pool-shutdown-exception"></a>

このエラーは、基盤となる Apache HTTP 接続プールが閉じられたことを示します。以下の項目は、潜在的な原因です。
+ **SDK クライアントが途中で閉じられた。 **SDK は、関連付けられたクライアントが閉じられたときにのみ接続プールを閉じます。使用中はリソースを閉じないでください。
+ **`java.lang.Error` がスローされた。**`OutOfMemoryError` などのエラーにより、Apache HTTP 接続プールが[シャットダウンされます](https://github.com/apache/httpcomponents-client/blob/6a741b4f8f23e6c5c7cc42c36c2acabfac19c3d6/httpclient/src/main/java/org/apache/http/impl/execchain/MainClientExec.java#L368)。ログでエラースタックトレースがないかを調べてください。また、 `Throwable` または `Error` をキャッチするものの、エラーが無視されて表面化していない場所についても、コードを確認してください。コードでエラーが報告されない場合は、情報がログに記録されるようにコードを書き換えます。ログに記録された情報は、エラーの根本原因を特定するのに役立ちます。
+ **閉じられた後に `DefaultCredentialsProvider#create()` から返された認証情報プロバイダーを使用しようとした**。[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()) はシングルトンインスタンスを返すため、閉じられてコードが `resolveCredentials` メソッドを呼び出すと、キャッシュされた認証情報 (またはトークン) の有効期限が切れた後に例外がスローされます。

  次の例に示すように、`DefaultCredentialsProvider` が閉じられている場所をコードで確認します。
  + シングルトンインスタンスは、`DefaultCredentialsProvider#close().` を呼び出すことで閉じられます。

    ```
    DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create(); // Singleton instance returned.
    AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
    
    // Make calls to AWS のサービス.
    
    defaultCredentialsProvider.close();  // Explicit close.
    
    // Make calls to 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();
    ```
  + try-with-resources ブロックで `DefaultCredentialsProvider#create()` を呼び出します。

    ```
    try (DefaultCredentialsProvider defaultCredentialsProvider = DefaultCredentialsProvider.create()) {
        AwsCredentials credentials = defaultCredentialsProvider.resolveCredentials();
        
        // Make calls to AWS のサービス.
    
    } // After the try-with-resources block exits, the singleton DefaultCredentialsProvider is closed.
    
    // Make calls to 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();
    ```

  コードがシングルトンインスタンスを閉じており、`DefaultCredentialsProvider` を使用して認証情報を解決する必要がある場合は、`DefaultCredentialsProvider.builder().build()` を呼び出して新しい非シングルトンインスタンスを作成します。

## 「Unable to load credentials from any of the providers in the chain AwsCredentialsProviderChain」を修正するにはどうすればよいですか?
<a name="faq-credentials-provider-chain"></a>

このエラーは、 がデフォルトの AWS 認証情報プロバイダーチェーン内の認証情報プロバイダーを通じて有効な認証情報を見つけ AWS SDK for Java 2.x られなかったことを示します。SDK は特定の順序で認証情報を自動的に検索します。このエラーは、チェーン内のすべてのプロバイダーが有効な認証情報を提供できなかった場合に発生します。

通常、完全なエラーメッセージは次のようになります (読みやすくするために行の末尾とインデントを追加しています）。

```
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.]
```

### 一般的な原因と解決方法
<a name="faq-cred-provider-chain-common-causes-and-solutions"></a>

#### 認証情報設定を確認する
<a name="faq-cred-provider-chain-check-config"></a>

デフォルトの認証情報プロバイダーを (認証情報を明示的に設定せずに `ServiceClient.create()` を呼び出して） 使用する場合、SDK は特定の順序で認証情報を検索します。[デフォルトの認証情報プロバイダーチェーンの仕組み](credentials-chain.md)を確認し、SDK が検索する認証情報ソースと順序を理解します。

使用する認証情報設定方法が環境で適切に設定されていることを確認します。

##### Amazon EC2 インスタンスの場合
<a name="faq-cred-check-ec2"></a>
+ **IAM ロールを確認する:** IAM ロールがインスタンスにアタッチされていることを確認します。
+ **断続的な IMDS 障害:** 断続的な障害 (通常は数百ミリ秒継続) が発生した場合、これは通常、インスタンスメタデータサービス (IMDS) に到達する一時的なネットワークの問題を示します。

  解決方法:
  + [デバッグログ](logging-slf4j.md#sdk-debug-level-logging)を有効にして障害のタイミングと頻度を分析する
  + アプリケーションに認証情報関連の障害に対する再試行ロジックを実装することを検討する
  + インスタンスと IMDS エンドポイント間のネットワーク接続の問題を確認する

##### コンテナ環境の場合
<a name="faq-cred-check-container-env"></a>

タスクロール (Amazon ECS) またはサービスアカウント (Amazon EKS) が設定され、必要な環境変数が設定されていることを確認します。

##### ローカル開発の場合
<a name="faq-cred-check-local-dev"></a>

環境変数、認証情報ファイル、または IAM Identity Center が設定されていることを確認します。

##### ウェブ ID フェデレーションの場合
<a name="faq-cred-check-web-id-federation"></a>
+ **設定を検証する: **ウェブ ID トークンファイルが存在し、必要な環境変数が設定されていることを確認します。
+ **STS モジュールの依存関係がない:** エラー `To use web identity tokens, the 'sts' service module must be on the class path` が表示された場合は、STS モジュールを依存関係として追加する必要があります。これは、Amazon EKS Pod Identity または他のウェブ ID トークン認証を使用する場合に一般的です。

  解決方法: STS モジュールをプロジェクトの依存関係に追加します。
  + 

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

    一部のサービスでは、`aws-query-protocol` 依存関係も必要になる場合があります。

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

#### ネットワークまたはプロキシの接続の問題
<a name="faq-credentials-provider-chain-network-issues"></a>

認証情報プロバイダーチェーンに `Connection refused` エラーが表示される場合、これは通常、SDK が AWS エンドポイントに到達しようとしたときにネットワーク接続の問題が発生したことを示します。

**解決方法:**
+ プロキシサーバーを使用している場合は、プロキシ設定を確認する
+ ネットワークが AWS エンドポイントへのアウトバウンド HTTPS 接続を許可していることを確認します。
+ [デバッグログ](logging-slf4j.md#sdk-debug-level-logging)を有効にして接続の試行の詳細を表示する
+ `curl` などのツールを使用して接続をテストし、 AWS エンドポイントへのネットワークアクセスを検証する

# の SDK 起動時間を短縮する AWS Lambda
<a name="lambda-optimize-starttime"></a>

の目標の 1 AWS SDK for Java 2.x つは、 関数の起動レイテンシーを減らすことです AWS Lambda 。SDK には、起動時間を短縮する変更が含まれています。これについてはこのトピックの最後で説明します。

まず、このトピックでは、コールド起動時間を短縮するためにできる変更に焦点を当てます。これには、コード構造やサービスクライアントの設定の変更が含まれます。

## CRT ベースの AWS HTTP クライアントを使用する
<a name="lambda-quick-url"></a>

を使用するには AWS Lambda、同期シナリオ[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)の場合は を、非同期シナリオ[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)の場合は を使用することをお勧めします。

このガイドの [CRT AWS ベースの HTTP クライアントを設定する](http-configuration-crt.md) トピックでは、HTTP クライアントを使用する利点、依存関係を追加する方法、サービスクライアントによる使用を設定する方法について説明します。

## 未使用の HTTP クライアント依存関係を削除する
<a name="lambda-quick-remove-deps"></a>

CRT ベースのクライアントの明示的な使用に加えて、SDK AWS がデフォルトで導入する他の HTTP クライアントを削除できます。ロードする必要のあるライブラリが少ないほど、Lambda の起動時間は短くなるため、JVM がロードする必要のある未使用のアーティファクトはすべて削除する必要があります。

以下の Maven `pom.xml` ファイルのスニペットは、Apache ベースの HTTP クライアントと Netty ベースの HTTP クライアントが除外されていることを示しています。( AWS CRT ベースのクライアントを使用する場合、これらのクライアントは必要ありません）。この例では、HTTP クライアントアーティファクトを S3 クライアントの依存関係から除外し、アー`aws-crt-client`ティファクトを追加して AWS CRT ベースの HTTP クライアントへのアクセスを許可します。

```
<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>
```

**注記**  
`pom.xml` ファイル内のすべてのサービスクライアント依存関係に `<exclusions>` 要素を追加します。

## 検索をショートカットするようにサービスクライアントを設定します。
<a name="lambda-quick-clients"></a>

**リージョンを指定する**  
サービスクライアントを作成したら、サービスクライアントビルダーの `region` メソッドを呼び出します。これにより、SDK のデフォルトの[リージョン検索プロセス](region-selection.md#default-region-provider-chain)がショートカットされ、複数の場所で AWS リージョン 情報がチェックされます。  
Lambda コードをリージョンから独立させるには、`region` メソッド内で以下のコードを使用します。このコードは、Lambda コンテナによって設定された `AWS_REGION` 環境変数にアクセスします。  

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

**`EnvironmentVariableCredentialProvider` の使用**  
リージョン情報のデフォルトの検索動作と同様に、SDK は複数の場所で認証情報を検索します。サービスクライアントを構築するときに [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) を指定することで、SDK の認証情報検索処理にかかる時間を短縮できます。  
この認証情報プロバイダーを使用すると、コードは Lambda 関数で使用できますが、 Amazon EC2 や他のシステムでは機能しない場合があります。  
どこかの時点で [Lambda SnapStart for Java](#lambda-quick-snapstart) を使用する場合は、デフォルトの認証情報プロバイダーチェーンを使用して認証情報を検索する必要があります。`EnvironmentVariableCredentialsProvider` を指定した場合、最初の認証情報ルックアップは機能しますが、SnapStart がアクティブ化されると [Java ランタイムはコンテナ認証情報の環境変数を設定します](https://docs.aws.amazon.com/lambda/latest/dg/snapstart-activate.html#snapstart-credentials)。アクティベーション時に、`EnvironmentVariableCredentialsProvider` が使用する環境変数 (アクセスキー環境変数) は Java SDK では使用できません。

以下のコードスニペットは、Lambda 環境で使用するために適切に設定された S3 サービスクライアントを示しています。

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

## Lambda 関数ハンドラーの外部で SDK クライアントを初期化する
<a name="lambda-quick-initialize"></a>

Lambda ハンドラーメソッドの外部で SDK クライアントを初期化することをお勧めします。これにより、実行コンテキストが再利用される場合、サービスクライアントの初期化をスキップできます。クライアントインスタンスとその接続を再利用することで、それ以降のハンドラーメソッドの呼び出しがより迅速に行われます。

以下の例では、`S3Client` インスタンスは静的ファクトリーメソッドを使用してコンストラクターで初期化されます。Lambda 環境で管理されているコンテナが再利用されると、初期化された `S3Client` インスタンスが再利用されます。

```
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.
    }
}
```

## 依存関係インジェクションを最小限に抑える
<a name="lambda-quick-di"></a>

依存関係インジェクション (DI) フレームワークを使用すると、設定プロセスの完了までにさらに時間がかかる場合があります。また、追加の依存関係が必要になる可能性もあり、読み取りに時間がかかります。

DI フレームワークが必要な場合は、[Dagger](https://dagger.dev/dev-guide/) などの軽量な DI フレームワークの使用をお勧めします。

## Maven Archetype ターゲットを使用する AWS Lambda
<a name="lambda-quick-maven"></a>

 AWS Java SDK チームは、最小限の起動時間で Lambda プロジェクトをブートストラップするための [Maven Archetype](https://github.com/aws/aws-sdk-java-v2/tree/master/archetypes/archetype-lambda) テンプレートを開発しました。アーキタイプから Maven プロジェクトを構築し、依存関係が Lambda 環境に合わせて適切に設定されていることを確認できます。

アーキタイプおよびデプロイ例について知るには、この[ブログ記事](https://aws.amazon.com/blogs/developer/bootstrapping-a-java-lambda-application-with-minimal-aws-java-sdk-startup-time-using-maven/)を参照してください。

## Lambda SnapStart for Java を検討する
<a name="lambda-quick-snapstart"></a>

ランタイム要件に互換性がある場合、 は [Lambda SnapStart for Java ](https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html) AWS を提供します。Lambda SnapStart は、Java 関数の起動パフォーマンスを向上させるインフラストラクチャベースのソリューションです。新しいバージョンの関数を発行する場合、Lambda SnapStart は初期化され、メモリとディスクの状態の変更不可能な暗号化されたスナップショットを作成します。その後、SnapStart はスナップショットをキャッシュして再利用します。

## 起動時間に影響するバージョン 2.x の変更点
<a name="example-client-configuration"></a>

コードに加えた変更に加えて、SDK for Java のバージョン 2.x には、起動時間を短縮する 3 つの主な変更が含まれています。
+ 初期化時間を短縮するシリアル化ライブラリである、[Jackson-jr](https://github.com/FasterXML/jackson-jr) を使用します
+ JDK の一部である日付時刻オブジェクトで [java.time](https://docs.oracle.com/javase/8/docs/api/index.html?java/time.html) ライブラリを使用します。
+ ログ記録ファサードの [Slf4j](https://www.slf4j.org/) を使用します

## その他のリソース
<a name="lambda-quick-resources"></a>

 AWS Lambda デベロッパーガイドには、Java 固有ではない Lambda 関数を開発するための[ベストプラクティスに関するセクション](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html)が含まれています。

が使用する Java でクラウドネイティブアプリケーションを構築する例については AWS Lambda、この[ワークショップのコンテンツ](https://github.com/aws-samples/aws-lambda-java-workshop)を参照してください。ワークショップでは、パフォーマンスの最適化やその他のベストプラクティスについて説明します。

起動時のレイテンシーを短縮するために、事前にコンパイルされた静的イメージの使用を検討できます。例えば、SDK for Java 2.x および Maven を使用して [GraalVM ネイティブイメージを構築](setup-project-graalvm.md)できます。

# `ContentStreamProvider` で を実装する AWS SDK for Java 2.x
<a name="content-stream-provider"></a>

`ContentStreamProvider` は、入力データの複数の読み取りを可能にする AWS SDK for Java 2.x ために で使用される抽象化です。このトピックでは、アプリケーションに `ContentStreamProvider` を正しく実装する方法について説明します。

SDK for Java 2.x は、ストリーム全体を読み取る必要があるたびに `ContentStreamProvider#newStream()` メソッドを使用します。ストリーム全体でこれを使用するには、返されるストリームが常にコンテンツの先頭にあり、同じデータが含まれている必要があります。

以下のセクションでは、この動作を正しく実装するための 3 つのアプローチを示します。

## `mark()` および `reset()` を使用します。
<a name="csp-impl-mark-reset"></a>

以下の例では、ストリームを最初に戻すことができるように、読み取りを開始する前にコンストラクタで `mark(int)` を使用します。`newStream()` の呼び出しごとに、ストリームをリセットします。

```
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;  
    }  
}
```

## `mark()` と `reset()` が利用できない場合にバッファリングを使用する
<a name="csp-impl-unsupported-streams"></a>

 ストリームが `mark()` と `reset()` を直接サポートしていない場合でも、最初に `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;  
    }  
}
```

## 新しいストリームを作成する
<a name="csp-impl-new-stream"></a>

より簡単な方法は、単に呼び出しごとにデータへの新しいストリームを取得し、前のストリームを閉じることです。

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

# DNS 名参照用の JVM TTL を設定する
<a name="jvm-ttl-dns"></a>

Java 仮想マシン (JVM) は DNS 名参照をキャッシュします。JVM がホスト名を IP アドレスに変換するとき、*time-to-live* (TTL) と呼ばれる指定期間 IP アドレスをキャッシュします。

 AWS リソースは DNS 名エントリを使用するため、TTL 値を 5 秒に設定することをお勧めします。これにより、リソースの IP アドレスが変更されたときに、アプリケーションは DNS に対して再度クエリを実行することで、リソースの新しい IP アドレスを取得し、使用できるようになります。

一部の Java 設定では JVM のデフォルトの TTL が設定されるため、JVM が再起動されるまで、DNS エントリが更新されることは*ありません*。したがって、アプリケーションの実行中に AWS リソースの IP アドレスが変更された場合、JVM *を手動で再起動*し、キャッシュされた IP 情報が更新されるまで、そのリソースを使用することはできません。この場合、キャッシュされた IP 情報が定期的に更新されるように JVM の TTL を設定することが極めて重要です。

## JVM TTL を設定する方法
<a name="how-to-set-the-jvm-ttl"></a>

JVM の TTL を変更するには、[networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/17/core/java-networking.html#GUID-A680DADB-C4C1-40F1-B568-D9A97C917F5D) セキュリティプロパティ値を設定します。`networkaddress.cache.ttl` は*セキュリティプロパティ*であり、システムプロパティではありません。つまり、`-D`コマンドラインフラグで設定することはできません。

### オプション 1: アプリケーションでプログラムで設定する
<a name="set-ttl-programmatically"></a>

 AWS SDK クライアントが作成される前、およびネットワークリクエストが行われる前に、アプリケーション起動の[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)早い段階で を呼び出します。

```
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
    }
}
```

### オプション 2: java.security ファイルで設定する
<a name="set-ttl-java-security-file"></a>

Java 8 の場合は `$JAVA_HOME/jre/lib/security/java.security` ファイル、Java 11 以降の場合は `$JAVA_HOME/conf/security/java.security` ファイルで `networkaddress.cache.ttl`プロパティを設定します。

以下は、TTL キャッシュが 5 秒に設定された `java.security` ファイルからのスニペットです。

```
#
# 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
...
```

`$JAVA_HOME` 環境変数で表される JVM で実行されるすべてのアプリケーションは、この設定を使用します。

### オプション 3: JDK システムプロパティのフォールバックを使用する (コマンドライン)
<a name="set-ttl-system-property"></a>

セキュリティ設定またはコードを変更できない場合は、JDK システムプロパティを使用できます。セキュリティプロパティが定義されていない場合、これらはフォールバックとして機能します。
+ `sun.net.inetaddr.ttl` – 正常なルックアップを制御する (正の TTL)
+ `sun.net.inetaddr.negative.ttl` – 失敗したルックアップを制御する (負の TTL)

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

**注記**  
これらは、「Oracle [Java 8 Networking Properties](https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html) reference as private properties that " may not be supported in future releases」に記載されている JDK 内部プロパティです。可能な場合はオプション 1～2 を使用します。

# AWS SDK for Java で HTTP/2 を使用する
<a name="http2"></a>

HTTP/2 は HTTP プロトコルのメジャーバージョンです。この新しいバージョンには、パフォーマンスを向上させるために次のようないくつかの機能強化が図られています。
+ より効率的なデータ転送を実現するバイナリデータのエンコーディング。
+ ヘッダーの圧縮により、クライアントによってダウンロードされるオーバーヘッドバイトが減り、クライアントにコンテンツをより速く提供できます。これは特に、既に帯域幅の制限を受けているモバイルクライアントで役立ちます。
+ 双方向非同期通信 (多重化) により、複数の接続ではなく 1 回の接続で同時にクライアントと AWS 間の複数のリクエストおよび応答メッセージをフライト状態にすることができ、これによりパフォーマンスが向上します。

最新の SDK にアップグレードする開発者は、使用中のサービスでサポートされている場合、自動的に HTTP/2 を使用します。新しいプログラミングインターフェイスはシームレスに HTTP/2 を活用して、アプリケーションを構築するための新しい方法を提供します。

AWS SDK for Java 2.x は、HTTP/2 プロトコルを実装するイベントストリーミング用の新しい API を備えています。これらの新しい API の使用方法の例については、[Kinesis の使用](examples-kinesis.md)を参照してください。