JavaでS3にアクセスする場合には、
が候補に挙がります。メンテナンスされており、機能が豊富である一方、これらのライブラリは依存ライブラリが非常に多いです。
AWS SDK for Java 2.0の場合、
\- software.amazon.awssdk:s3:jar:2.26.16:compile
+- software.amazon.awssdk:aws-xml-protocol:jar:2.26.16:compile
| \- software.amazon.awssdk:aws-query-protocol:jar:2.26.16:compile
+- software.amazon.awssdk:protocol-core:jar:2.26.16:compile
+- software.amazon.awssdk:arns:jar:2.26.16:compile
+- software.amazon.awssdk:profiles:jar:2.26.16:compile
+- software.amazon.awssdk:crt-core:jar:2.26.16:compile
+- software.amazon.awssdk:http-auth:jar:2.26.16:compile
+- software.amazon.awssdk:identity-spi:jar:2.26.16:compile
+- software.amazon.awssdk:http-auth-spi:jar:2.26.16:compile
| \- org.reactivestreams:reactive-streams:jar:1.0.4:compile
+- software.amazon.awssdk:http-auth-aws:jar:2.26.16:compile
+- software.amazon.awssdk:checksums:jar:2.26.16:compile
+- software.amazon.awssdk:checksums-spi:jar:2.26.16:compile
+- software.amazon.awssdk:retries-spi:jar:2.26.16:compile
+- software.amazon.awssdk:sdk-core:jar:2.26.16:compile
| +- software.amazon.awssdk:retries:jar:2.26.16:compile
| \- org.slf4j:slf4j-api:jar:2.0.13:compile
+- software.amazon.awssdk:auth:jar:2.26.16:compile
| \- software.amazon.eventstream:eventstream:jar:1.0.1:compile
+- software.amazon.awssdk:http-client-spi:jar:2.26.16:compile
+- software.amazon.awssdk:regions:jar:2.26.16:compile
+- software.amazon.awssdk:annotations:jar:2.26.16:compile
+- software.amazon.awssdk:utils:jar:2.26.16:compile
+- software.amazon.awssdk:aws-core:jar:2.26.16:compile
+- software.amazon.awssdk:metrics-spi:jar:2.26.16:compile
+- software.amazon.awssdk:json-utils:jar:2.26.16:compile
| \- software.amazon.awssdk:third-party-jackson-core:jar:2.26.16:compile
+- software.amazon.awssdk:endpoints-spi:jar:2.26.16:compile
+- software.amazon.awssdk:apache-client:jar:2.26.16:runtime
| +- org.apache.httpcomponents:httpclient:jar:4.5.13:runtime
| | \- commons-logging:commons-logging:jar:1.2:runtime
| +- org.apache.httpcomponents:httpcore:jar:4.4.16:runtime
| \- commons-codec:commons-codec:jar:1.16.1:runtime
\- software.amazon.awssdk:netty-nio-client:jar:2.26.16:runtime
+- io.netty:netty-codec-http:jar:4.1.111.Final:runtime
+- io.netty:netty-codec-http2:jar:4.1.111.Final:runtime
+- io.netty:netty-codec:jar:4.1.111.Final:runtime
+- io.netty:netty-transport:jar:4.1.111.Final:runtime
+- io.netty:netty-common:jar:4.1.111.Final:runtime
+- io.netty:netty-buffer:jar:4.1.111.Final:runtime
+- io.netty:netty-handler:jar:4.1.111.Final:runtime
| \- io.netty:netty-transport-native-unix-common:jar:4.1.111.Final:runtime
+- io.netty:netty-transport-classes-epoll:jar:4.1.111.Final:runtime
\- io.netty:netty-resolver:jar:4.1.111.Final:runtime
MinIO Java SDKの場合、
\- io.minio:minio:jar:8.5.11:compile
+- com.carrotsearch.thirdparty:simple-xml-safe:jar:2.7.1:compile
+- com.google.guava:guava:jar:33.0.0-jre:compile
| +- com.google.guava:failureaccess:jar:1.0.2:compile
| +- com.google.guava:listenablefuture:jar:9999.0-empty-to-avoid-conflict-with-guava:compile
| +- com.google.code.findbugs:jsr305:jar:3.0.2:compile
| +- org.checkerframework:checker-qual:jar:3.41.0:compile
| +- com.google.errorprone:error_prone_annotations:jar:2.23.0:compile
| \- com.google.j2objc:j2objc-annotations:jar:2.8:compile
+- com.squareup.okhttp3:okhttp:jar:4.12.0:compile
| +- com.squareup.okio:okio:jar:3.6.0:compile
| | \- com.squareup.okio:okio-jvm:jar:3.6.0:compile
| | \- org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.9.24:compile
| \- org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.9.24:compile
| +- org.jetbrains.kotlin:kotlin-stdlib:jar:1.9.24:compile
| | \- org.jetbrains:annotations:jar:13.0:compile
| \- org.jetbrains.kotlin:kotlin-stdlib-jdk7:jar:1.9.24:compile
+- com.fasterxml.jackson.core:jackson-annotations:jar:2.17.1:compile
+- com.fasterxml.jackson.core:jackson-core:jar:2.17.1:compile
+- com.fasterxml.jackson.core:jackson-databind:jar:2.17.1:compile
+- org.bouncycastle:bcprov-jdk18on:jar:1.78:compile
+- org.apache.commons:commons-compress:jar:1.26.0:compile
| +- commons-io:commons-io:jar:2.15.1:compile
| \- org.apache.commons:commons-lang3:jar:3.14.0:compile
+- commons-codec:commons-codec:jar:1.16.1:compile
\- org.xerial.snappy:snappy-java:jar:1.1.10.5:compile
となります。
Note
EoLが近づいているAWS SDK for Javaの場合は、幾分ましな依存関係です。
\- com.amazonaws:aws-java-sdk-s3:jar:1.12.757:compile
+- com.amazonaws:aws-java-sdk-kms:jar:1.12.757:compile
+- com.amazonaws:aws-java-sdk-core:jar:1.12.757:compile
| +- commons-logging:commons-logging:jar:1.1.3:compile
| +- commons-codec:commons-codec:jar:1.16.1:compile
| +- org.apache.httpcomponents:httpclient:jar:4.5.13:compile
| | \- org.apache.httpcomponents:httpcore:jar:4.4.16:compile
| +- com.fasterxml.jackson.core:jackson-databind:jar:2.17.1:compile
| | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.17.1:compile
| | \- com.fasterxml.jackson.core:jackson-core:jar:2.17.1:compile
| +- com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:jar:2.17.1:compile
| \- joda-time:joda-time:jar:2.12.7:compile
\- com.amazonaws:jmespath-java:jar:1.12.757:compile
他のAWSのサービスも使用している場合は、AWS SDK for Java 2.0でも良いかもしれませんが、
例えば、S3互換なObject Storageにシンプルなput/getくらいしかしていない場合は、これらのライブラリはtoo muchです。
また、AWS SDKの場合はApache HTTP Client or Netty、MinIO SDKの場合は(Kotlinで実装された)OkHttpとHTTPクライアントがそれぞれ組み込まれています。
Spring Bootでアプリを作成する場合、通常RestTemplateやRestClientを使用します。
SDK側でHTTPクライアントが別途使われている場合、アプリ側で設定したObservability, Logging, RetryなどのInterceptorを共通的に利用できなくなり不便です。
アクセスキーとシークレットキーによる認証でput/getくらいしかしないようなシンプルなユースケースでは、単純にS3用にHTTP Headersを作成し、XMLのマーシャル・アンマーシャルだけ行えれば十分です。
それはSDKを使わずともRestTemplateやRestClientだけで事足ります。
というわけでsimple-s3-clientというライブラリを作りました。
"s3-client"という名前がついていますが、HTTP Headersを作るユーティリティとよく使うAPIのデータクラスが含まれているだけです。
以下のdependencyを追加すれば使えます。
<dependency>
<groupId>am.ik.s3</groupId>
<artifactId>simple-s3-client</artifactId>
<version>0.2.2</version>
</dependency>
使い方は次の通りです。
import static am.ik.s3.S3RequestBuilder.s3Request;
URI endpoint = URI.create("https://...");
String region = "...";
String accessKeyId = "...";
String secretAccessKey = "...";
String bucket = "...";
ObjectのPUTは次のように行えます。
// Put an object
String body = "Hello World!";
S3Request putObjectRequest = s3Request().endpoint(endpoint)
.region(region)
.accessKeyId(accessKeyId)
.secretAccessKey(secretAccessKey)
.method(HttpMethod.PUT)
.path(b -> b.bucket(bucket).key("hello.txt"))
.content(S3Content.of(body, MediaType.TEXT_PLAIN))
.build();
RestTemplateの場合
restTemplate.exchange(putObjectRequest.toEntityBuilder().body(body), Void.class);
RestClientの場合
restClient.put()
.uri(putObjectRequest.uri())
.headers(putObjectRequest.headers())
.body(body)
.retrieve()
.toBodilessEntity();
Note
マルチパートは未対応です。
ObjectのGETは次のように行えます。
// Get an object
S3Request getObjectRequest = s3Request().endpoint(endpoint)
.region(region)
.accessKeyId(accessKeyId)
.secretAccessKey(secretAccessKey)
.method(HttpMethod.GET)
.path(b -> b.bucket(bucket).key("hello.txt"))
.build();
RestTemplateの場合
String response = restTemplate.exchange(getObjectRequest.toEntityBuilder().build(), String.class).getBody();
System.out.println("Response: " + response); // Response: Hello World!
RestClientの場合
String response = restClient.get()
.uri(getObjectRequest.uri())
.headers(getObjectRequest.headers())
.retrieve()
.body(String.class);
System.out.println("Response: " + response); // Response: Hello World!
その他の使い方はREADMEを確認してください。
依存ライブラリは次の通りで、Spring BootでWebアプリを作るのに必須なspring-webとJacksonでXMLを扱うためのjackson-dataformat-xmlだけなので、
一般的なSpring Bootアプリ観点ではjackson-dataformat-xmlが足されただけで済みます。
\- am.ik.s3:simple-s3-client:jar:0.2.2:compile
+- org.springframework:spring-web:jar:6.1.10:compile
| +- org.springframework:spring-beans:jar:6.1.10:compile
| +- org.springframework:spring-core:jar:6.1.10:compile
| | \- org.springframework:spring-jcl:jar:6.1.10:compile
| \- io.micrometer:micrometer-observation:jar:1.13.1:compile
| \- io.micrometer:micrometer-commons:jar:1.13.1:compile
+- com.fasterxml.jackson.dataformat:jackson-dataformat-xml:jar:2.17.1:compile
| +- com.fasterxml.jackson.core:jackson-core:jar:2.17.1:compile
| +- com.fasterxml.jackson.core:jackson-annotations:jar:2.17.1:compile
| +- com.fasterxml.jackson.core:jackson-databind:jar:2.17.1:compile
| \- org.codehaus.woodstox:stax2-api:jar:4.2.2:compile
\- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.17.1:compile