How to use AWS SDK Clients in Spring Boot environment with externalized properties

Intro

As Java developer i’ve seen many methods that devers uses to interact with AWS SDK in the Spring Boot environment, but i prefer this style among all others xD

Normally, when using AWS SDK for Java clients in Spring environment, i advise you to use each client as a bean, write Java configuration as follows.

AWS SDK Client in Spring environment

  @Bean
  public AmazonS3 amazonS3() {
    return AmazonS3ClientBuilder.defaultClient();
  }

Each client, can be created individually  with a bunch of configuration like connectionTimeout killing socketTimeout started, you have a variety of settings. The above amazonS3 can only be configured by modifying the code and rebuilding.

  @Bean
  public AmazonSQS amazonSQS() {
    ClientConfiguration clientConfig = new ClientConfiguration()
        .withConnectionTimeout(1300)
        .withSocketTimeout(23000);
    return AmazonSQSClientBuilder.standard()
        .withClientConfiguration(clientConfig)
        .build();
  }

In the above amazonSQS, the timeout value is set, but since this is also a hard-coded value, you cannot change the setting value unless you modify the code and rebuild.

  @Bean
  public AmazonSNS amazonSNS(
      @Value("aws.sns.endpoint.your-service-endpoint") String yourServiceEndpoint,
      @Value("aws.sns.endpoint.you-signing-region") String yourSigningRegion) {
    EndpointConfiguration endpointConfig = new EndpointConfiguration(yourServiceEndpoint, yourSigningRegion);
    return AmazonSNSClientBuilder.standard()
        .withEndpointConfiguration(endpointConfig)
        .build();
  }

With this amazonSNS, you can switch the API endpoint URL to a mock ( localstack, etc.), but you cannot set a timeout.

  @Bean
  public AmazonDynamoDB amazonDynamoDB(@Value("yourdynamodb.region") String region) {
    return AmazonDynamoDBClientBuilder.standard()
        .withRegion(region)
        .build();
  }

dynamoDB you can also set the region, but its property nomenclature is inconsistent. aws.dynamodb.region is reasonable to follow the rules of SNS clients ?

  @Bean
  public S3Client s3Client() {
    return S3Client.create(); // AWS SDK for Java v2!!
  }

s3Client is an implementation of the AWS SDK for Java 2.0 , how did I set this up?

Be careful :  If you define a client naively, you will struggle with many kind of problems.

The external setting function is a function for operation.

If you can, you want to control it as a unified property without rebuilding various settings. There is a certain merit that it is easy for the operation staff to control various application settings instead of the development staff in case of emergency.

In the first place, the ability to « change settings externally without rebuilding » is called Externalized Configuration in Spring Boot .

Spring Boot’s Externalized Configuration is a mechanism that allows you to search for settings in the following priority (order) and refer to the first value found in your application.

  1. Settings described in the test
  2. $ java -jar foobar.jar Command line arguments when started with
  3. Java system properties
  4. OS environment variables
  5. application-{profile}.properties Files in the classpath
  6. application.properties Files in the classpath

Even if 1 is a little bit exceptional, the point is that 2 to 4, which are easy for operations or some debuggings staffs ( or fetching some property system to a Lambda from EC2 or the JVM system property  » i ll write a tutorial about this » ) , have a higher priority. Developers will use 5 to 6 mechanisms to define default values.

So how to use externalized properties and inject beans ?

@Configuration
@EnableAwsBeans({
  AmazonDynamoDB.class,
  AmazonSES.class,
  AmazonS3.class
  
}
  )
@EnableAwsBeans(S3Client.class)
public class AwsClientConfiguration {
}

In addition, application.properties write the following in the classpath .

aws.sqs.client.connection-timeout = 1300
aws.sqs.client.socket-timeout = 23000

Now the operations person AWS_SQS_CLIENT_CONNECTION_TIMEOUT=9000 can change the connection timeout for the SQS client to 9 seconds by defining it as an environment variable .

Sample application

@Slf4j
@RequiredArgsConstructor
@SpringBootApplication
@EnableAwsBeans(AmazonEC2.class)
public class DummyApplication implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(DummyApplication.class, args);
  }

  private final AmazonEC2 ec2;

  @Override
  public void run(String... args) throws Exception {
   var regions= ec2.describeRegions().getRegions();
       regions.stream()
      .map(region->region.getRegionName())
      .forEach(logger::info);
  }
}

Performs the EC2 DescribeRegions action and eu-central-1 logs all region names ( and so on). 

By the way, the AWS SDK for Java v2 seems to look like this. It’s almost the same. It’s close to finding a mistake.

@Slf4j
@RequiredArgsConstructor
@SpringBootApplication
@EnableAwsBeans(Ec2Client.class)
static class DummyApplication implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(DummyApplication.class, args);
  }


  private final Ec2Client ec2;


  @Override
  public void run(String... args) throws Exception {
    var regions= ec2.describeRegions().getRegions();
       regions.stream()
      .map(region->region.getRegionName())
      .forEach(logger::info););
  }
}

Summary

I hope that this mechanism can be used to easily proceed with AWS service verification work.

I hope you all have a good year.


Votre commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l’aide de votre compte WordPress.com. Déconnexion /  Changer )

Image Twitter

Vous commentez à l’aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l’aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s