

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 適用於 Java 的 AWS SDK 遷移工具
<a name="migration-tool"></a>

 適用於 Java 的 AWS SDK 提供遷移工具，可協助自動將適用於 Java 的 SDK 1.x (V1) 程式碼遷移至 2.x (V2)。此工具使用開放原始碼、原始程式碼重構工具 [OpenRewrite](https://docs.openrewrite.org/) 來執行遷移。OpenRewrite 使用程式碼修改規則 （稱為「配方」)，將您的原始程式碼從 V1 自動更新為 V2 語法和模式。

此工具支援 SDK 服務用戶端和 [S3 Transfer Manager](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferManager.html) 高階程式庫的程式碼修改規則。不支援其他高階 APIs的程式碼修改規則，例如 V1 [https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.html](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/datamodeling/DynamoDBMapper.html)到 V2 的 [DynamoDB 增強型用戶端 API](dynamodb-enhanced-client.md)。

如需限制的詳細資訊，請參閱[此頁面的結尾](#migration-tool-limitations)。如需手動遷移步驟的常見不支援程式碼模式的詳細範例，請參閱[不支援的程式碼模式](migration-tool-unsupported-patterns.md)。

## 使用遷移工具
<a name="migration-tool-use"></a>

### 遷移 Maven 專案
<a name="migration-tool-use-maven"></a>

請依照下列指示，使用 [OpenRewrite Maven 外掛程式工具遷移適用於 Java 的 SDK 1.x Maven](https://docs.openrewrite.org/reference/rewrite-maven-plugin) 型專案。

1. 導覽至 Maven 專案的根目錄

   開啟終端機 （命令列） 視窗，然後導覽至 Maven 型應用程式的根目錄。

1. 執行外掛程式的`rewrite-maven-plugin`命令

   您可以選擇兩種模式 (Maven 目標）： `dryRun`和 `run`。

   **`dryRun`**** 模式**

   在 `dryRun`模式中，外掛程式會在主控台輸出中產生 diff 日誌，並在 `target/rewrite` 資料夾中產生名為 `rewrite.patch`的修補程式檔案。此模式可讓您預覽將要進行的變更，因為原始程式碼檔案不會進行任何變更。

   下列範例示範如何在 `dryRun` 模式中叫用 外掛程式。

   ```
   mvn org.openrewrite.maven:rewrite-maven-plugin:<rewrite-plugin-version>*:dryRun \
     -Drewrite.recipeArtifactCoordinates=software.amazon.awssdk:v2-migration:<sdkversion>** \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

   \$1將 *<rewrite-plugin-version>* 取代為您在此[測試檔案中](https://github.com/aws/aws-sdk-java-v2/blob/3a01289246f1f4ac814a354051d00030e53ef968/test/v2-migration-tests/src/test/java/software/amazon/awssdk/v2migrationtests/MavenTestBase.java#L54)看到`rewriteMavenPluginVersion`的值。

   \$1\$1以 2.x SDK 版本取代 *<sdkversion>*。請造訪 [Maven Central](https://central.sonatype.com/artifact/software.amazon.awssdk/v2-migration) 以檢查是否有最新版本。
**重要**  
請務必使用[測試檔案中](https://github.com/aws/aws-sdk-java-v2/blob/3a01289246f1f4ac814a354051d00030e53ef968/test/v2-migration-tests/src/test/java/software/amazon/awssdk/v2migrationtests/MavenTestBase.java#L54)`rewrite-maven-plugin`顯示的 版本，因為其他版本可能無法運作。

   來自 `dryRun` 模式的主控台輸出應該類似下列輸出。

   ```
   [WARNING] These recipes would make changes to project/src/test/resources/maven/before/pom.xml:
   [WARNING]     software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   [WARNING]         software.amazon.awssdk.v2migration.UpgradeSdkDependencies
   [WARNING]             org.openrewrite.java.dependencies.AddDependency: {groupId=software.amazon.awssdk, artifactId=apache-client, version=2.27.0, onlyIfUsing=com.amazonaws.ClientConfiguration}
   [WARNING]             org.openrewrite.java.dependencies.AddDependency: {groupId=software.amazon.awssdk, artifactId=netty-nio-client, version=2.27.0, onlyIfUsing=com.amazonaws.ClientConfiguration}
   [WARNING]             org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=com.amazonaws, oldArtifactId=aws-java-sdk-bom, newGroupId=software.amazon.awssdk, newArtifactId=bom, newVersion=2.27.0}
   [WARNING]             org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=com.amazonaws, oldArtifactId=aws-java-sdk-s3, newGroupId=software.amazon.awssdk, newArtifactId=s3, newVersion=2.27.0}
   [WARNING]             org.openrewrite.java.dependencies.ChangeDependency: {oldGroupId=com.amazonaws, oldArtifactId=aws-java-sdk-sqs, newGroupId=software.amazon.awssdk, newArtifactId=sqs, newVersion=2.27.0}
   [WARNING] These recipes would make changes to project/src/test/resources/maven/before/src/main/java/foo/bar/Application.java:
   [WARNING]     software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   [WARNING]         software.amazon.awssdk.v2migration.S3GetObjectConstructorToFluent
   [WARNING]             software.amazon.awssdk.v2migration.ConstructorToFluent
   [WARNING]         software.amazon.awssdk.v2migration.S3StreamingResponseToV2
   [WARNING]         software.amazon.awssdk.v2migration.ChangeSdkType
   [WARNING]         software.amazon.awssdk.v2migration.ChangeSdkCoreTypes
   [WARNING]             software.amazon.awssdk.v2migration.ChangeExceptionTypes
   [WARNING]                 org.openrewrite.java.ChangeType: {oldFullyQualifiedTypeName=com.amazonaws.AmazonClientException, newFullyQualifiedTypeName=software.amazon.awssdk.core.exception.SdkException}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getRequestId(), newMethodName=requestId}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getErrorCode(), newMethodName=awsErrorDetails().errorCode}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getServiceName(), newMethodName=awsErrorDetails().serviceName}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getErrorMessage(), newMethodName=awsErrorDetails().errorMessage}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getRawResponse(), newMethodName=awsErrorDetails().rawResponse().asByteArray}
   [WARNING]                 org.openrewrite.java.ChangeMethodName: {methodPattern=com.amazonaws.AmazonServiceException getRawResponseContent(), newMethodName=awsErrorDetails().rawResponse().asUtf8String}
   [WARNING]                 org.openrewrite.java.ChangeType: {oldFullyQualifiedTypeName=com.amazonaws.AmazonServiceException, newFullyQualifiedTypeName=software.amazon.awssdk.awscore.exception.AwsServiceException}
   [WARNING]         software.amazon.awssdk.v2migration.NewClassToBuilderPattern
   [WARNING]             software.amazon.awssdk.v2migration.NewClassToBuilder
   [WARNING]             software.amazon.awssdk.v2migration.V1SetterToV2
   [WARNING]         software.amazon.awssdk.v2migration.V1GetterToV2
   ...
   [WARNING]         software.amazon.awssdk.v2migration.V1BuilderVariationsToV2Builder
   [WARNING]         software.amazon.awssdk.v2migration.NewClassToBuilderPattern
   [WARNING]             software.amazon.awssdk.v2migration.NewClassToBuilder
   [WARNING]             software.amazon.awssdk.v2migration.V1SetterToV2
   [WARNING]         software.amazon.awssdk.v2migration.HttpSettingsToHttpClient
   [WARNING]         software.amazon.awssdk.v2migration.WrapSdkClientBuilderRegionStr
   [WARNING] Patch file available:
   [WARNING]     project/src/test/resources/maven/before/target/rewrite/rewrite.patch
   [WARNING] Estimate time saved: 20m
   [WARNING] Run 'mvn rewrite:run' to apply the recipes.
   ```

   **`run`**** 模式**

   當您在 `run` 模式下執行外掛程式時，它會修改磁碟上的原始碼以套用變更。執行 命令之前，請確定您有原始程式碼的備份。

   下列範例示範如何在 `run` 模式中叫用 外掛程式。

   ```
   mvn org.openrewrite.maven:rewrite-maven-plugin:<rewrite-plugin-version>*:run \
     -Drewrite.recipeArtifactCoordinates=software.amazon.awssdk:v2-migration:<sdkversion>** \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

   \$1將 *<rewrite-plugin-version>* 取代為您在此[測試檔案中](https://github.com/aws/aws-sdk-java-v2/blob/3a01289246f1f4ac814a354051d00030e53ef968/test/v2-migration-tests/src/test/java/software/amazon/awssdk/v2migrationtests/MavenTestBase.java#L54)看到`rewriteMavenPluginVersionvalue`的 。

   \$1\$1將 *<sdkversion>* 取代為 2.x SDK 版本。請造訪 [Maven Central](https://central.sonatype.com/artifact/software.amazon.awssdk/v2-migration) 以檢查是否有最新版本。

   執行 命令後，編譯您的應用程式並執行測試以驗證變更。

### 遷移 Gradle 專案
<a name="migration-tool-use-gradle"></a>

請依照下列指示，使用 [OpenRewrite Gradle 外掛程式工具遷移適用於 Java 的 SDK 1.x Gradle](https://docs.openrewrite.org/reference/gradle-plugin-configuration) 型專案。

1. 導覽至 Gradle 專案的根目錄

   開啟終端機 （命令列） 視窗，然後導覽至 Gradle 型應用程式的根目錄。

1. 建立 Gradle init 指令碼

   在 目錄中建立具有下列內容`init.gradle`的檔案。

   ```
   initscript {
       repositories {
           maven { url "https://plugins.gradle.org/m2" }
       }
       dependencies {
           classpath("org.openrewrite:plugin:<rewrite-plugin-version>*")
       }
   }
   
   rootProject {
       plugins.apply(org.openrewrite.gradle.RewritePlugin)
       dependencies {
           rewrite("software.amazon.awssdk:v2-migration:latest.release")
       }
   
       afterEvaluate {
           if (repositories.isEmpty()) {
               repositories {
                   mavenCentral()
               }
           }
       }
   }
   ```

   \$1將 *<rewrite-plugin-version>* 取代為您在此[測試檔案中](https://github.com/aws/aws-sdk-java-v2/blob/master/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/gradle/before/init.gradle#L6)看到的版本。

1. 執行 `rewrite`命令

   如同 Maven 外掛程式，您可以在 `dryRun`或 `run` 模式中執行 Gradle 外掛程式。

   **`dryRun` 模式**

   下列範例示範如何在 `dryRun` 模式中叫用 外掛程式。

   ```
   gradle rewriteDryRun --init-script init.gradle \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

   **`run` 模式**

   下列範例示範如何在 `run` 模式中叫用 外掛程式。

   ```
   gradle rewriteRun --init-script init.gradle \
     -Drewrite.activeRecipes=software.amazon.awssdk.v2migration.AwsSdkJavaV1ToV2
   ```

## 目前限制
<a name="migration-tool-limitations"></a>

雖然遷移透過更新至 V2 對等的程式碼修改規則來升級大多數 V1 程式碼，但某些類別和方法不會涵蓋在內。 V2 對於這些類別和方法，請依照[step-by-step指示](migration-steps.md)手動遷移您的程式碼。

對於某些不支援的程式碼修改規則，遷移工具可能會新增以下列開頭的註解：

```
/*AWS SDK for Java v2 migration: Transform for ...
```

在註解之後，工具會輸出方法或類別的 V2 版本一般 Stub。例如，在下列輸出中，遷移工具嘗試遷移 V1 S3 用戶端`setBucketLifecycleConfiguration`的方法：

```
/*AWS SDK for Java v2 migration: Transform for setBucketLifecycleConfiguration method not supported. 
Please manually migrate your code by using builder pattern, update from BucketLifecycleConfiguration.Rule 
to LifecycleRule, StorageClass to TransitionStorageClass, and adjust imports and names.*/
s3.putBucketLifecycleConfiguration(
        PutBucketLifecycleConfigurationRequest.builder()
            .bucket(bucketName)
            .lifecycleConfiguration(BucketLifecycleConfiguration.builder()
                .build())
            .build());
```

下方清單中的連結會帶您前往遷移資訊，以協助您手動遷移程式碼。
+ [第 1 版和第 2 版之間的 S3 用戶端差異 適用於 Java 的 AWS SDK](migration-s3-client.md)
+ [S3 Transfer Manager](migration-s3-transfer-manager.md) (TransferManager)
+ [DynamoDB 物件映射](migration-ddb-mapper.md) (DynamoDBMapper)
+ [EC2 中繼資料公用程式](migration-imds.md) (EC2MetadataUtils)
+ [等待程式](migration-waiters.md) (AmazonDynamoDBWaiters)
+ [IAM 政策建置器](migration-iam-policy-builder.md) （政策）
+ [CloudFront 預先簽署 ](migration-cloudfront-presigning.md)(CloudFrontUrlSigner、CloudFrontCookieSigner)
+ [S3 事件通知 ](migration-s3-event-notification.md)(S3EventNotification)
+ SDK 指標發佈 ([1.x 文件](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/generating-sdk-metrics.html)、[2.x 文件](metrics.md))
+ [不支援的程式碼模式](migration-tool-unsupported-patterns.md) – 需要手動遷移的常見程式碼模式的詳細範例

# 遷移工具不支援的程式碼模式
<a name="migration-tool-unsupported-patterns"></a>

遷移工具會自動將大多數 v1 程式碼轉換為 v2。不過，某些程式碼模式需要手動遷移。本主題提供最常見的不支援模式的詳細範例，並說明如何手動轉換。

下列模式清單並不詳盡。如果您的程式碼在執行遷移工具後未編譯，請依照[step-by-step遷移說明](migration-steps.md)手動遷移剩餘的 v1 程式碼。

## 使用參數請求物件建構函數
<a name="request-pojo-constructors"></a>

對於請求 POJOs(Amazon S3 除外），遷移工具只會轉換設定程式方法。此工具不支援具有參數的建構函數。

**支援的模式：使用設定器請求物件 （無建構器參數）**

之前 （原始 v1 程式碼）：

```
import com.amazonaws.services.sqs.model.SendMessageRequest;

SendMessageRequest request = new SendMessageRequest().withMessageBody("Hello World");
request.setQueueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue");
```

After （遷移工具結果）：

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;

SendMessageRequest request = SendMessageRequest.builder()
    .messageBody("Hello World").build();
request = request.toBuilder()
    .queueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue").build();
```

**不支援的模式：使用參數請求物件建構函數**

遷移工具無法轉換具有參數的建構函數：

在手動遷移之前，但在遷移工具之後：

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest; // Import updated to v2.

// This pattern requires manual migration.
SendMessageRequest request = new SendMessageRequest(
    "https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue", 
    "Hello World");
```

遷移工具會將匯入轉換為 v2，但建構函式程式碼保持不變，且需要手動更新才能使用建置器模式。

手動遷移之後：

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;

SendMessageRequest request = SendMessageRequest.builder()
    .messageBody("Hello World")
    .queueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue")
    .build();
```

## 具有個別參數的服務用戶端方法
<a name="service-client-method-overloads"></a>

遷移工具無法轉換採用個別參數的服務用戶端方法，而非請求物件 (Amazon S3 除外）。

之前 (v1 程式碼）：

```
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;

AmazonSQS sqs = new AmazonSQSClient();
// The following v1 method takes individual parameters.
sqs.sendMessage("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue", "Hello World");
```

After （遷移工具結果 – 未編譯）：

```
import software.amazon.awssdk.services.sqs.SqsClient;  // Import updated to v2.
// No import statement for the v2 request POJO.

SqsClient sqs = SqsClient.builder().build();

// Does not compile–v2 methods only accept request POJOs.
sqs.sendMessage("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue", "Hello World");
```

您必須手動更新方法引數，才能使用請求物件：

```
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.SendMessageRequest; // Add manually.

SqsClient sqs = SqsClient.builder().build();

// Corrected v2 code.
SendMessageRequest request = SendMessageRequest.builder()
    .queueUrl("https://sqs.us-west-2.amazonaws.com/0123456789012/demo-queue")
    .messageBody("Hello World")
    .build();
sqs.sendMessage(request);
```

## 請求逾時方法
<a name="request-pojo-timeout-configuration"></a>

遷移工具不會轉換在請求物件上設定逾時的方法。

之前 (v1 程式碼）：

```
import com.amazonaws.services.sqs.model.SendMessageRequest;

SendMessageRequest request = new SendMessageRequest();
request.setSdkRequestTimeout(7);
```

After （遷移工具結果 – 未編譯）：

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;  // Import updated to v2.

SendMessageRequest request = SendMessageRequest.builder().build();

// Does not compile.
request.setSdkRequestTimeout(7);
```

您必須手動遷移以使用 v2 的 `overrideConfiguration`方法：

```
import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
import java.time.Duration;

SendMessageRequest request = SendMessageRequest.builder().build();

// Corrected v2 code.
request = request.toBuilder()
    .overrideConfiguration(o -> o.apiCallTimeout(Duration.ofSeconds(7)))
    .build();
```

## 具有參數的服務用戶端建構函數
<a name="service-client-constructors-with-args"></a>

遷移工具會轉換空的服務用戶端建構函數，但無法轉換接受登入資料或組態等參數的建構函數。

之前 (v1 程式碼）：

```
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;

AWSCredentials awsCredentials = new BasicAWSCredentials("akid", "skid");
AmazonSQS sqs = new AmazonSQSClient(awsCredentials);
```

After （遷移工具結果 – 未編譯）：

```
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.services.sqs.SqsClient;  // Import updated to v2.

AwsCredentials awsCredentials = AwsBasicCredentials.create("akid", "skid");

// Does not compile.
SqsClient sqs = new SqsClient(awsCredentials);
```

您必須手動更新服務用戶端建構函數，才能使用建置器模式：

```
import software.amazon.awssdk.auth.credentials.AwsCredentials;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;  // Add manually.
import software.amazon.awssdk.services.sqs.SqsClient;

AwsCredentials awsCredentials = AwsBasicCredentials.create("akid", "skid");

// Corrected v2 code.
SqsClient sqs = SqsClient.builder()
    .credentialsProvider(StaticCredentialsProvider.create(awsCredentials))
    .build();
```