Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AmazonS3ClientBuilder.defaultClient() fails to account for region?

The Amazon Java SDK has marked the Constructors for AmazonS3Client deprecated in favor of some AmazonS3ClientBuilder.defaultClient(). Following the recommendation, though, does not result in an AmazonS3 client that works the same. In particular, the client has somehow failed to account for Region. If you run the tests below, the thisFails test demonstrates the problem.

public class S3HelperTest {
  @Test
  public void thisWorks() throws Exception {
    AmazonS3 s3Client = new AmazonS3Client();  // this call is deprecated
    s3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
    assertNotNull(s3Client);
  }

  @Test
  public void thisFails() throws Exception {
    AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient();
    /*
     * The following line throws like com.amazonaws.SdkClientException:
     * Unable to find a region via the region provider chain. Must provide an explicit region in the builder or
     * setup environment to supply a region.
     */
    s3Client.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build());
  }
}

com.amazonaws.SdkClientException: Unable to find a region via the region provider chain. Must provide an explicit region in the builder or setup environment to supply a region.
    at com.amazonaws.client.builder.AwsClientBuilder.setRegion(AwsClientBuilder.java:371)
    at com.amazonaws.client.builder.AwsClientBuilder.configureMutableProperties(AwsClientBuilder.java:337)
    at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
    at com.amazonaws.services.s3.AmazonS3ClientBuilder.defaultClient(AmazonS3ClientBuilder.java:54)
    at com.climate.tenderfoot.service.S3HelperTest.thisFails(S3HelperTest.java:21)
    ...

Is this an AWS SDK Bug? Is there some "region default provider chain" or some mechanism to derive the region from the Environment and set it into the client? It seems really weak that the method to replace the deprecation doesn't result in the same capability.

like image 543
Bob Kuhar Avatar asked Oct 11 '17 20:10

Bob Kuhar


People also ask

What is the default region for all SDKS?

AWS clients created by using the client constructor will not automatically determine region from the environment and will, instead, use the default SDK region (USEast1). When running on Amazon EC2 or Lambda, you might want to configure clients to use the same region that your code is running on.

Does S3 client need region?

“S3 does not require region selection.” Also, you will notice that all the regions are greyed out and you actually can't change the region. However, the confusion starts when we create a bucket. Because the creation of a bucket always requires us to choose a region.

Which is the correct syntax to create a client for making use of AWS kms with the help of SDKS client builder?

To create an AWS KMS client in Java, use the client builder. AWSKMS kmsClient = AWSKMSClientBuilder. standard().

Is Java AWS SDK thread safe?

Service clients in the SDK are thread-safe and, for best performance, you should treat them as long-lived objects. Each client has its own connection pool resource.


1 Answers

Looks like a region is required for the builder. Probably this thread is related (I would use .withRegion(Regions.US_EAST_1) though in the 3rd line):

To emulate the previous behavior (no region configured), you'll need to also enable "forced global bucket access" in the client builder:

AmazonS3 client = 
        AmazonS3ClientBuilder.standard()
                             .withRegion("us-east-1") // The first region to try your request against
                             .withForceGlobalBucketAccess(true) // If a bucket is in a different region, try again in the correct region
                             .build();

This will suppress the exception you received and automatically retry the request under the region in the exception. It is made explicit in the builder so you are aware of this cross-region behavior. Note: The SDK will cache the bucket region after the first failure, so that every request against this bucket doesn't have to happen twice.


Also, from the AWS documentation if you want to use AmazonS3ClientBuilder.defaultClient(); then you need to have ~/.aws/credentials and ~/.aws/config files

~/.aws/credentials contents:

[default]
aws_access_key_id = your_id
aws_secret_access_key = your_key

~/.aws/config contents:

[default]
region = us-west-1

From the same AWS documentation page, if you don't want to hardcode the region/credentials, you can have it as environment variables in your Linux machine the usual way:

export AWS_ACCESS_KEY_ID=your_access_key_id
export AWS_SECRET_ACCESS_KEY=your_secret_access_key
export AWS_REGION=your_aws_region
like image 54
Battle_Slug Avatar answered Sep 21 '22 01:09

Battle_Slug