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.
- Settings described in the test
$ java -jar foobar.jar
Command line arguments when started with- Java system properties
- OS environment variables
application-{profile}.properties
Files in the classpathapplication.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.