Transfer Manager を AWS SDK for Java のバージョン 1 からバージョン 2 に移行する
この移行ガイドでは、Transfer Manager v1 と S3 Transfer Manager v2 の主な違いについて説明します。これには、コンストラクタの変更、メソッドマッピング、一般的なオペレーションのコード例が含まれます。これらの違いを知ることで、既存の Transfer Manager コードを正常に移行して、v2 でのパフォーマンスの向上と非同期オペレーションを活用できます。
AWS SDK 移行ツールについて
AWS SDK for Java には、v1 Transfer Manager API の大部分を v2 に移行できる自動移行ツールが用意されています。ただし、移行ツールは一部の v1 Transfer Manager 機能をサポートしていません。このような場合は、このトピックのガイダンスを使用して Transfer Manager コードを手動で移行する必要があります。
このガイド全体で、移行ステータスは、移行ツールがコンストラクタ、メソッド、または機能を自動的に移行できるかどうかを示します。
-
サポート対象: 移行ツールでこのコードを自動的に変換できます
-
サポート対象外: コードを手動で移行する必要があります
「サポート対象」とマークされた項目であっても、移行結果を確認して入念にテストしてください。Transfer Manager の移行には、同期オペレーションから非同期オペレーションへの大幅なアーキテクチャ変更が含まれます。
概要
S3 Transfer Manager v2 では、Transfer Manager API に大幅な変更が加えられました。S3 Transfer Manager v2 は非同期オペレーションを土台としており、特に AWS CRT ベースの Amazon S3 クライアントを使用する場合にパフォーマンスが向上します。
主な違い
-
パッケージ:
com.amazonaws.services.s3.transfer→software.amazon.awssdk.transfer.s3 -
クラス名:
TransferManager→S3TransferManager -
クライアントの依存関係: 同期 Amazon S3 クライアント → 非同期 Amazon S3 クライアント (
S3AsyncClient) -
アーキテクチャ: 同期オペレーション →
CompletableFutureを使用した非同期オペレーション -
パフォーマンス: AWS CRT ベースのクライアントサポートで強化
高レベル変更
| 側面 | V1 | V2 |
|---|---|---|
| Maven の依存関係 | aws-java-sdk-s3 |
s3-transfer-manager |
| パッケージ: | com.amazonaws.services.s3.transfer |
software.amazon.awssdk.transfer.s3 |
| メインクラス | TransferManager |
S3TransferManager |
| Amazon S3 クライアント | AmazonS3 (同期) |
S3AsyncClient (非同期) |
| 戻り型 | ブロックオペレーション | CompletableFuture<T> |
Maven の依存関係
| V1 | V2 |
|---|---|
|
|
1 最新バージョン
クライアントコンストラクタの移行
サポート対象コンストラクタ (自動移行)
| V1 コンストラクタ | V2 の同等コンストラクタ | 移行ステータス |
|---|---|---|
new TransferManager() |
S3TransferManager.create() |
サポート対象 |
TransferManagerBuilder.
defaultTransferManager() |
S3TransferManager.create() |
サポート対象 |
TransferManagerBuilder.
standard().build() |
S3TransferManager.builder().build() |
サポート対象 |
new TransferManager(AWSCredentials) |
S3TransferManager.builder()
.s3Client(S3AsyncClient.builder()
.credentialsProvider(...).build())
.build() |
サポート対象 |
new TransferManager(
AWSCredentialsProvider) |
S3TransferManager.builder()
.s3Client(S3AsyncClient.builder()
.credentialsProvider(...).build())
.build() |
サポート対象 |
サポート対象外コンストラクタ (手動移行が必要)
| V1 コンストラクタ | V2 の同等コンストラクタ | 移行に関するメモ |
|---|---|---|
new TransferManager(AmazonS3) |
手動移行が必要 | S3AsyncClient を個別に作成する |
new TransferManager(AmazonS3,
ExecutorService) |
手動移行が必要 | S3AsyncClient を作成し、エグゼキュターを設定する |
new TransferManager(AmazonS3,
ExecutorService, boolean) |
手動移行が必要 | shutDownThreadPools パラメータはサポートされていません |
手動移行の例
V1 コード:
AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
TransferManager transferManager = new TransferManager(s3Client);
V2 コード:
// Create an `S3AsyncClient` with similar configuration
S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
.credentialsProvider(DefaultCredentialsProvider.create())
.build();
// Provide the configured `S3AsyncClient` to the S3 transfer manager builder.
S3TransferManager transferManager = S3TransferManager.builder()
.s3Client(s3AsyncClient)
.build();
クライアントメソッドの移行
現在、移行ツールは基本的な copy、download、upload、uploadDirectory、downloadDirectory、resumeDownload、および resumeUpload メソッドをサポートしています。
主な転送メソッド
| V1 メソッド | V2 メソッド | 戻り型の変更 | 移行ステータス |
|---|---|---|---|
upload(String, String, File) |
uploadFile(UploadFileRequest) |
Upload → FileUpload |
サポート対象 |
upload(PutObjectRequest) |
upload(UploadRequest) |
Upload → Upload |
サポート対象 |
download(String, String, File) |
downloadFile(DownloadFileRequest) |
Download → FileDownload |
サポート対象 |
download(GetObjectRequest, File) |
downloadFile(DownloadFileRequest) |
Download → FileDownload |
サポート対象 |
copy(String, String, String, String) |
copy(CopyRequest) |
Copy → Copy |
サポート対象 |
copy(CopyObjectRequest) |
copy(CopyRequest) |
Copy → Copy |
サポート対象 |
uploadDirectory(String, String,
File, boolean) |
uploadDirectory(
UploadDirectoryRequest) |
MultipleFileUpload →
DirectoryUpload |
サポート対象 |
downloadDirectory(String, String, File) |
downloadDirectory(
DownloadDirectoryRequest) |
MultipleFileDownload →
DirectoryDownload |
サポート対象 |
再開可能な転送メソッド
| V1 メソッド | V2 メソッド | 移行ステータス |
|---|---|---|
resumeUpload(PersistableUpload) |
resumeUploadFile(ResumableFileUpload) |
サポート対象 |
resumeDownload(PersistableDownload) |
resumeDownloadFile(ResumableFileDownload) |
サポート対象 |
ライフサイクルメソッド
| V1 メソッド | V2 メソッド | 移行ステータス |
|---|---|---|
shutdownNow() |
close() |
サポート対象 |
shutdownNow(boolean) |
close() メソッドを使用してコードを手動で調整する |
サポート外 |
サポートされていない V1 クライアントメソッド
| V1 メソッド | V2 代替メソッド | メモ |
|---|---|---|
abortMultipartUploads(String, Date) |
低レベルの Amazon S3 クライアントを使用 | サポート外 |
getAmazonS3Client() |
リファレンスを個別に保存 | サポート対象外、v2 にはゲッターなし |
getConfiguration() |
リファレンスを個別に保存 | サポート対象外、v2 にはゲッターなし |
uploadFileList(...) |
複数の uploadFile() 呼び出しを行う |
サポート外 |
TransferStateChangeListener パラメータを持つ copy メソッド |
TransferListener を使用する |
手動移行の例を参照 |
S3ProgressListener パラメータを持つ download メソッド |
を使用するTransferListener |
手動移行の例を参照 |
|
4 つ以上のパラメータを持つ |
手動移行の例を参照 | |
ObjectMetadataProvider パラメータを使用した upload メソッド |
リクエストでメタデータを設定 | 手動移行の例を参照 |
*Provider パラメータを持つ uploadDirectory メソッド |
リクエストでタグを設定 | 手動移行の例を参照 |
TransferStateChangeListener パラメータを持つ copy メソッド
-
copy(CopyObjectRequest copyObjectRequest, AmazonS3 srcS3, TransferStateChangeListener stateChangeListener) -
copy(CopyObjectRequest copyObjectRequest, TransferStateChangeListener stateChangeListener)
// V1 ---------------------------------------------------------------------------------------------- // Initialize source S3 client AmazonS3 s3client = AmazonS3ClientBuilder.standard() .withRegion("us-west-2") .build(); // Initialize Transfer Manager TransferManager tm = TransferManagerBuilder.standard() .withS3Client(srcS3) .build(); CopyObjectRequest copyObjectRequest = new CopyObjectRequest( "amzn-s3-demo-source-bucket", "source-key", "amzn-s3-demo-destination-bucket", "destination-key" ); TransferStateChangeListener stateChangeListener = new TransferStateChangeListener() { @Override public void transferStateChanged(Transfer transfer, TransferState state) { //Implementation of the TransferStateChangeListener } }; Copy copy = tm.copy(copyObjectRequest, srcS3, stateChangeListener); // V2 ---------------------------------------------------------------------------------------------- S3AsyncClient s3AsyncClient = S3AsyncClient.builder() .region(Region.US_WEST_2) .build(); S3TransferManager transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build(); // Create transfer listener (equivalent to TransferStateChangeListener in v1) TransferListener transferListener = new TransferListener() { @Override public void transferInitiated(Context.TransferInitiated context) { //Implementation System.out.println("Transfer initiated"); } @Override public void bytesTransferred(Context.BytesTransferred context) { //Implementation System.out.println("Bytes transferred"); } @Override public void transferComplete(Context.TransferComplete context) { //Implementation System.out.println("Transfer completed!"); } @Override public void transferFailed(Context.TransferFailed context) { //Implementation System.out.println("Transfer failed"); } }; CopyRequest copyRequest = CopyRequest.builder() .copyObjectRequest(req -> req .sourceBucket("amzn-s3-demo-source-bucket") .sourceKey("source-key") .destinationBucket("amzn-s3-demo-destination-bucket") .destinationKey("destination-key") ) .addTransferListener(transferListener) // Configure the transferListener into the request .build(); Copy copy = transferManager.copy(copyRequest);
S3ProgressListener パラメータを持つ download メソッド
-
download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener) -
download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis) -
download(GetObjectRequest getObjectRequest, File file, S3ProgressListener progressListener, long timeoutMillis, boolean resumeOnRetry)
// V1 ---------------------------------------------------------------------------------------------- S3ProgressListener progressListener = new S3ProgressListener() { @Override public void progressChanged(com.amazonaws.event.ProgressEvent progressEvent) { long bytes = progressEvent.getBytesTransferred(); ProgressEventType eventType = progressEvent.getEventType(); // Use bytes and eventType as needed } @Override public void onPersistableTransfer(PersistableTransfer persistableTransfer) { } }; Download download1 = tm.download(getObjectRequest, file, progressListener); Download download2 = tm.download(getObjectRequest, file, progressListener, timeoutMillis) Download download3 = tm.download(getObjectRequest, file, progressListener, timeoutMillis, true) // V2 ---------------------------------------------------------------------------------------------- TransferListener transferListener = new TransferListener() { @Override public void transferInitiated(Context.InitializedContext context) { // Equivalent to ProgressEventType.TRANSFER_STARTED_EVENT System.out.println("Transfer initiated"); } @Override public void bytesTransferred(Context.BytesTransferred context) { // Equivalent to ProgressEventType.REQUEST_BYTE_TRANSFER_EVENT long bytes = context.bytesTransferred(); System.out.println("Bytes transferred: " + bytes); } @Override public void transferComplete(Context.TransferComplete context) { // Equivalent to ProgressEventType.TRANSFER_COMPLETED_EVENT System.out.println("Transfer completed"); } @Override public void transferFailed(Context.TransferFailed context) { // Equivalent to ProgressEventType.TRANSFER_FAILED_EVENT System.out.println("Transfer failed: " + context.exception().getMessage()); } }; DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder() .getObjectRequest(getObjectRequest) .destination(file.toPath()) .addTransferListener(transferListener) .build(); // For download1 FileDownload download = transferManager.downloadFile(downloadFileRequest); // For download2 CompletedFileDownload completedFileDownload = download.completionFuture() .get(timeoutMillis, TimeUnit.MILLISECONDS); // For download3, the v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1. // If a download is interrupted, you need to start a new download request.
4 つ以上のパラメータを持つ downloadDirectory メソッド
-
downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry) -
downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, boolean resumeOnRetry, KeyFilter filter) -
downloadDirectory(String bucketName, String keyPrefix, File destinationDirectory, KeyFilter filter)
// V1 ---------------------------------------------------------------------------------------------- KeyFilter filter = new KeyFilter() { @Override public boolean shouldInclude(S3ObjectSummary objectSummary) { //Filter implementation } }; MultipleFileDownload multipleFileDownload = tm.downloadDirectory(bucketName, keyPrefix, destinationDirectory, filter); // V2 ---------------------------------------------------------------------------------------------- // The v2 SDK does not have a direct equiavalent to the `resumeOnRetry` method of v1. // If a download is interrupted, you need to start a new download request. DownloadFilter filter = new DownloadFilter() { @Override public boolean test(S3Object s3Object) { // Filter implementation. } }; DownloadDirectoryRequest downloadDirectoryRequest = DownloadDirectoryRequest.builder() .bucket(bucketName) .filter(filter) .listObjectsV2RequestTransformer(builder -> builder.prefix(keyPrefix)) .destination(destinationDirectory.toPath()) .build(); DirectoryDownload directoryDownload = transferManager.downloadDirectory(downloadDirectoryRequest);
ObjectMetadata パラメータを持つ upload メソッド
-
upload(String bucketName, String key, InputStream input, ObjectMetadata objectMetadata)
// V1 ----------------------------------------------------------------------------------------------ObjectMetadata metadata = new ObjectMetadata(); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType("text/plain"); // System-defined metadata metadata.setContentLength(22L); // System-defined metadata metadata.addUserMetadata("myKey", "myValue"); // User-defined metadata PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream, metadata); Upload upload = transferManager.upload("amzn-s3-demo-bucket", "my-key", inputStream, metadata); // V2 ---------------------------------------------------------------------------------------------- /* When you use an InputStream to upload in V2, you should specify the content length and use `RequestBody.fromInputStream()`. If you don't provide the content length, the entire stream will be buffered in memory. If you can't determine the content length, we recommend using the CRT-based S3 client. */ Map<String, String> userMetadata = new HashMap<>(); userMetadata.put("x-amz-meta-myKey", "myValue"); PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket("amzn-s3-demo-bucket1") .key("k") .contentType("text/plain") //System-defined metadata usually has separate methods in the builder. .contentLength(22L) .metadata(userMetadata) //metadata() is only for user-defined metadata. .build(); UploadRequest uploadRequest = UploadRequest.builder() .putObjectRequest(putObjectRequest) .requestBody(AsyncRequestBody.fromInputStream(stream, 22L, executor)) .build(); transferManager.upload(uploadRequest).completionFuture().join();
ObjectMetadataProvider パラメータを持つ uploadDirectory
-
uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider) -
uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider) -
uploadDirectory(String bucketName, String virtualDirectoryKeyPrefix, File directory, boolean includeSubdirectories, ObjectMetadataProvider metadataProvider, ObjectTaggingProvider taggingProvider, ObjectCannedAclProvider cannedAclProvider)
// V1 ---------------------------------------------------------------------------------------------- tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider) tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider) tm.uploadDirectory(bucketName, virtualDirectoryKeyPrefix, directory, includeSubdirectories, metadataProvider, taggingProvider, cannedAclProvider) // V2 ---------------------------------------------------------------------------------------------- UploadDirectoryRequest request = UploadDirectoryRequest.builder() .bucket(bucketName) .s3Prefix(virtualDirectoryKeyPrefix) .source(directory.toPath()) .maxDepth(includeSubdirectories ? Integer.MAX_VALUE : 1) .uploadFileRequestTransformer(builder -> { // 1.Replace `ObjectMetadataProvider`, `ObjectTaggingProvider`, and `ObjectCannedAclProvider` with an // `UploadFileRequestTransformer` that can combine the functionality of all three *Provider implementations. // 2. Convert your v1 `ObjectMetadata` to v2 `PutObjectRequest` parameters. // 3. Convert your v1 `ObjectTagging` to v2 `Tagging`. // 4. Convert your v1 `CannedAccessControlList` to v2 `ObjectCannedACL`. }) .build(); DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);
モデルオブジェクトの移行
AWS SDK for Java 2.x では、多くの TransferManager モデルオブジェクトが再設計されており、v1 のモデルオブジェクトで使用できるいくつかのゲッターメソッドとセッターメソッドはサポートされなくなりました。
v2 では、 CompletableFuture<T> クラスを使用して、転送が (正常に、または例外を伴って) 完了したときにアクションを実行できます。必要に応じて、join() メソッドを使用して完了を待つことができます。
主な転送オブジェクト
| V1 クラス | V2 クラス | 移行ステータス |
|---|---|---|
TransferManager |
S3TransferManager |
サポート対象 |
TransferManagerBuilder |
S3TransferManager.Builder |
サポート対象 |
Transfer |
Transfer |
サポート対象 |
AbortableTransfer |
Transfer |
サポート対象 (個別のクラスなし) |
Copy |
Copy |
サポート対象 |
Download |
FileDownload |
サポート対象 |
Upload |
Upload / FileUpload |
サポート対象 |
MultipleFileDownload |
DirectoryDownload |
サポート対象 |
MultipleFileUpload |
DirectoryUpload |
サポート対象 |
永続性オブジェクト
| V1 クラス | V2 クラス | 移行ステータス |
|---|---|---|
PersistableDownload |
ResumableFileDownload |
サポート対象 |
PersistableUpload |
ResumableFileUpload |
サポート対象 |
PersistableTransfer |
ResumableTransfer |
サポート対象 |
PauseResult<T> |
直接再開可能なオブジェクト | サポート外 |
結果オブジェクト
| V1 クラス | V2 クラス | 移行ステータス |
|---|---|---|
CopyResult |
CompletedCopy |
サポート対象 |
UploadResult |
CompletedUpload |
サポート対象 |
構成オブジェクト
| V1 クラス | V2 クラス | 移行ステータス |
|---|---|---|
TransferManagerConfiguration |
MultipartConfiguration (Amazon S3 クライアント上) |
サポート対象 |
TransferProgress |
TransferProgress + TransferProgressSnapshot |
サポート対象 |
KeyFilter |
DownloadFilter |
サポート対象 |
サポートされていないオブジェクト
| V1 クラス | V2 代替メソッド | 移行ステータス |
|---|---|---|
PauseStatus |
サポートされません | サポート外 |
UploadContext |
サポートされません | サポート外 |
ObjectCannedAclProvider |
PutObjectRequest.builder().acl() |
サポート外 |
ObjectMetadataProvider |
PutObjectRequest.builder().metadata() |
サポート外 |
ObjectTaggingProvider |
PutObjectRequest.builder().tagging() |
サポート外 |
PresignedUrlDownload |
サポートされません | サポート外 |
TransferManagerBuilder の設定移行
設定変更
v2 Transfer Manager に設定する必要がある設定変更は、使用する S3 クライアントによって異なります。AWS CRT ベースの S3 クライアントまたは標準の Java ベースの S3 非同期クライアントのいずれかを選択できます。違いの詳細については、AWS SDK for Java 2.x の S3 クライアント トピックを参照してください。
動作の変更
非同期オペレーション
V1 (ブロック)
Upload upload = transferManager.upload("amzn-s3-demo-bucket", "key", file);
upload.waitForCompletion(); // Blocks until complete
V2 (非同期):
FileUpload upload = transferManager.uploadFile(UploadFileRequest.builder()
.putObjectRequest(PutObjectRequest.builder()
.bucket("amzn-s3-demo-bucket")
.key("key")
.build())
.source(file)
.build());
CompletedFileUpload result = upload.completionFuture().join(); // Blocks until complete
// Or handle asynchronously:
upload.completionFuture().thenAccept(result -> {
System.out.println("Upload completed: " + result.response().eTag());
});
エラー処理
V1: サブリクエストが失敗した場合、ディレクトリ転送は完全に失敗します。
V2: 一部のサブリクエストが失敗した場合でも、ディレクトリ転送は正常に完了します。エラーを明示的に確認します。
DirectoryUpload directoryUpload = transferManager.uploadDirectory(request);
CompletedDirectoryUpload result = directoryUpload.completionFuture().join();
// Check for failed transfers
if (!result.failedTransfers().isEmpty()) {
System.out.println("Some uploads failed:");
result.failedTransfers().forEach(failed ->
System.out.println("Failed: " + failed.exception().getMessage()));
}
バイト範囲フェッチによる並列ダウンロード
v2 SDK で自動並列転送機能が有効になっている場合、S3 Transfer Manager はバイト範囲フェッチを使用してオブジェクトの特定の部分を並列して取得します (マルチパートダウンロード)。v2 でのオブジェクトのダウンロード方法は、オブジェクトが最初にアップロードされた方法には依存しません。すべてのダウンロードで、高いスループットと同時実行性のメリットが得られます。
これとは対照的に、v1 の Transfer Manager では、オブジェクトが最初にどのようにアップロードされたかが問題になります。v1 の Transfer Manager は、パーツがアップロードされたのと同じ方法でオブジェクトの一部を取得します。オブジェクトが元々単一のオブジェクトとしてアップロードされた場合、v1 の Transfer Manager はサブリクエストを使用してダウンロードプロセスを高速化することはできません。