javaamazon-s3aws-sdkminio

How to using AWS S3 Java v2 SDK to talk to S3 compatible storage (minio)


I am trying to use software.amazon.awssdk:s3 S3Client to talk to a minio storage, but I cant find this in the official document: https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/using.html

Looks like it only supports AWS S3 service, the region config is compulsory.

I searched the internet but they are using v1 SDK.

Here is my S3Client but when I use an api it throws oftware.amazon.awssdk.core.exception.SdkClientException: Received an UnknownHostException when attempting to interact with a service. The hostname was modified as backend.localhost in the request.

String endpoint = "http://localhost:9000"
return S3Client
        .builder()
        .region(Region.of("minio"))
        .endpointOverride(new URI(endpoint))
        .credentialsProvider(() -> AwsBasicCredentials.create(accessKey, secretKey))
        .build();

// the request
s3Client.listObjects(ListObjectsRequest.builder().bucket("backend").build())

Solution

  • I've come across the same problem. My provisional solution was to create a custom endpoint provider. I've only tested this on getObject with minio so I don't know if it will work on other methods, but theoretically it should.

    s3Client = S3Client.builder()
                        .endpointProvider(new S3EndpointProvider() {
                            @Override
                            public CompletableFuture<Endpoint> resolveEndpoint(S3EndpointParams endpointParams) {
                                return CompletableFuture.completedFuture(Endpoint.builder()
                                        .url(URI.create(awsS3EndpointUrl + "/" + endpointParams.bucket()))
                                        .build());
                            }
                        })
                        // SDK requires us to provide region for local development, so we use a placeholder region here.
                        // The local instance doesn't have a specified region.
                        .region(Region.AWS_GLOBAL)
                        .credentialsProvider(() -> AwsBasicCredentials.create(awsAccessKeyId, awsAccessKeySecret))
                        .build();