Search code examples
javaamazon-web-servicesscalaamazon-s3aws-sdk-java-2.0

How to configure Region when using Java2 aws sdk?


I wrote the below controller to generate PreSigned S3 upload links.

case class S3Controller(private val s3Config: S3Config, private val awsConfig: AwsConfig) {
  val URL_TIMEOUT_IN_MILLIS: Long = 60 * 5 * 1000

  def getPreSignedURLForUpload(keyName: String): String = {
    val preSigner: S3Presigner = DefaultS3Presigner.builder()
      .serviceConfiguration(s3Config.s3Configuration)
      .credentialsProvider(awsConfig.awsCredentialsProvider).build()

    val objectRequest: PutObjectRequest = PutObjectRequest.builder()
      .bucket(s3Config.bucketName)
      .key(keyName)
      .contentType("text/plain")
      .build()

    val preSignRequest: PutObjectPresignRequest = PutObjectPresignRequest.builder()
      .signatureDuration(Duration.ofMinutes(10))
      .putObjectRequest(objectRequest)
      .build()

    val preSignedRequest: PresignedPutObjectRequest = preSigner.presignPutObject(preSignRequest)


    val myURL: String = preSignedRequest.url().toString

    myURL
  }
}

Config objects that I used

case class S3Config (
                      bucketName: String,
                      s3Configuration: S3Configuration
                    )
case class AwsConfig (
                       awsCredentialsProvider: AwsCredentialsProvider
                     )

I tried to test it with the following code

  test("S3 Controller"){
    val s3Configuration: S3Configuration = S3Configuration.builder()
      .pathStyleAccessEnabled(true).build()

    val s3Config: S3Config = S3Config(
      bucketName = "ccc",
      s3Configuration = s3Configuration
    )

    val awsCredentials: AwsCredentials = AwsBasicCredentials.create("aaa", "bbb")
    val awsCredentialsProvider: AwsCredentialsProvider = AwsCredentialsProviderChain.of(StaticCredentialsProvider.create(awsCredentials))
    
    val awsConfig: AwsConfig = AwsConfig(awsCredentialsProvider = awsCredentialsProvider)

    val s3Controller: S3Controller = S3Controller(s3Config, awsConfig)

    s3Controller.getPreSignedURLForUpload("ab")
  }

This test fails the with the messsage

Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@4e5ed836: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@5f8edcc5: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@60015ef5: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@2ab4bc72: Unable to contact EC2 metadata service.]
software.amazon.awssdk.core.exception.SdkClientException: Unable to load region from any of the providers in the chain software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain@4e5ed836: [software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@5f8edcc5: Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region)., software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@60015ef5: No region provided in profile: default, software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@2ab4bc72: Unable to contact EC2 metadata service.]

I understand this is happening since I've not configured the Region anywhere.
All the ways to configure the Region are either through environment variables or config files.

Is there a way to programmatically configure the Region?


Solution

  • YOu set a Region when you declare a Service Object using a builder():

    Region region = Region.US_EAST_1;
    S3Presigner presigner = S3Presigner.builder()
                    .region(region)
                    .build();
    

    All the Java V2 code examples show this way of setting a Region:

    https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javav2/example_code/s3/src/main/java/com/example/s3