AWS has changed the dependencies versions and naming convention in SDK 2.0
You can follow the AWS Developer Guide for more details
Upasana | September 09, 2019 | 4 min read | 986 views | AWS Tutorials
In this tutorial, we will walk through new AWS SDK 2.0 for doing message level operations on SQS queue. We will cover queue listing, send message and retrieve/delete message from SQS queue using AWS SDK 2.0
Configure Gradle Build
Creating Singleton Bean for SQS service client
Sending a message to SQS queue
Retrieving a message from SQS queue
Deleting messages from queue
The AWS SDK for Java 2.0 is a major rewrite of the version 1.x code base. It’s built on top of Java 8+ and adds several frequently requested features. These include support for non-blocking I/O and the ability to plug in a different HTTP implementation at run time.
Please be noted that you can still use AWS SDK 1.0 alongside SDK 2.0 in the same project. Since package naming is different, there will be absolutely no conflicts using the two versions in parallel in single project.
To use the AWS SDK for Java in your Gradle project, use Spring’s dependency management plugin for Gradle.
group 'foo.bar'
version '1.0'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation platform('software.amazon.awssdk:bom:2.5.29')
implementation 'software.amazon.awssdk:sqs' (1)
}
1 | Gradle automatically resolves the correct version of your SDK dependencies using the information from the BOM. No need to specify the version for service client libraries. |
To make requests to AWS, you first need to create a service client object (SqsClient for example). AWS SDK 2.0 provides service client builders to facilitate creation of service clients.
AWS SDK 2.0 has changed the class naming convention and removed AWS prefix from most of the classes. AmazonSQSClient
has been replaced with SqsClient
. When using Spring Boot, we can simply create bean of SqsClient and use it as and when required.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
@Configuration
public class SqsConfig {
@Bean
public SqsClient sqsClient(SqsConfig sqsConfig) {
SqsClient sqs = SqsClient.builder()
.credentialsProvider(StaticCredentialsProvider
.create(AwsBasicCredentials
.create(sqsConfig.getAccessKey(), sqsConfig.getSecretKey())))
.region(Region.of(sqsConfig.getRegion()))
.build();
return sqs;
}
}
Service clients in the SDK are thread-safe. For best performance, treat them as long-lived objects. Each client has its own connection pool resource that is released when the client is garbage collected. The clients in the AWS SDK for Java 2.0 now extend the AutoClosable interface. For best practices, explicitly close a client by calling the close method.
We can leverage SqsClient created in previous step to list queues for a given region and account.
ListQueuesResponse queues = sqsClient.listQueues();
final List<String> queueUrls = queues.queueUrls();
queueUrls.forEach(s -> logger.info(s));
We need to obtain queue url in order to make operations SQS queue.
GetQueueUrlResponse getQueueUrlResponse = sqsClient
.getQueueUrl(GetQueueUrlRequest.builder()
.queueName(queueName)
.build());
queueUrl = getQueueUrlResponse.queueUrl();
logger.info("Autoscaling queueUrl: {}", queueUrl);
This queueUrl will be used in next two sections for adding messages and retrieving messages from SQS queue.
SqsClient
provides a sendMessage
method that takes queueUrl and message payload that you want to publish to the SQS queue.
Once you have obtained the SQS url, then below code will allow you to publish message to the queue.
public class SqsMsg { (1)
String id;
//Getter & Setter removed for brevity
}
class ScratchPad {
public void addMessage(String identifier) {
SqsMsg msg = new SqsMsg(identifier);
final String asString;
try {
asString = objectMapper.writeValueAsString(msg);
sqsClient.sendMessage(SendMessageRequest.builder()
.queueUrl(queueUrl) (2)
.messageBody(asString)
.delaySeconds(1)
.build());
logger.info("Added msg {} to the queue", identifier);
} catch (JsonProcessingException e) {
logger.error("Error publishing msg to queue", e);
}
}
}
1 | SqsMsg defines the schema for message that we want to publish to SQS queue. |
2 | We obtained queueUrl in the previous step. |
sendMessage
returns SendMessageResponse
using which we can obtain the messageId
of recently published message.
The consumer application will retrieve the message from the Queue and delete it if successfully processed.
Here in the blow code, we are:
Getting one message from queue at a time
Converting the message into domain object using ObjectMapper class
Removing the message by providing the receipt handle
class ScratchPad {
public void removeMsg() throws IOException {
ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
.queueUrl(queueUrl)
.maxNumberOfMessages(1)
.build();
List<Message> messages = sqsClient.receiveMessage(receiveMessageRequest).messages();
for (Message message : messages) {
final String body = message.body();
final SqsMsg sqsMsg = objectMapper.readValue(body, SqsMsg.class);
logger.info("Delete msg: {}", sqsMsg);
DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
.queueUrl(queueUrl)
.receiptHandle(message.receiptHandle())
.build();
sqsClient.deleteMessage(deleteMessageRequest);
}
}
}
That’s all for now.