Home>>Tech>>Sending messages to Amazon SQS from a Spring Boot application
Tech

Sending messages to Amazon SQS from a Spring Boot application

We’re looking at yet another proof of concept (POC) application today. We’re going to see how we can integrate Amazon SQS, which stands for Simple Queue Service into our Spring Boot application so that we can send messages to the queue.

I’m going to use a few terms in this post which are influenced by Apache Kafka, because I come with extensive Kafka experience. However, I’m not going to compare Apache Kafka and Amazon SQS here. To clear things up, any service which sends a message to an SQS queue, I’ll refer to such a service as the producer. And any service which receives a message from an SQS queue, I’ll refer to that as the consumer. Now that we have that cleared up, let’s get started.


Creating an Amazon SQS queue

Creating an SQS queue is very simple. Head over to your AWS console, search for SQS in the console, you should see a page similar to the following screenshot, if there aren’t any queues already created.

AWS SQS Dashboard

Click the Get Started Now button you see in the centre of the page. There, you’ll see two options for the type of queue you want to create – standard and FIFO. Basically, FIFO is a special type of queue where the order of the message is maintained in the queue. You can see the explanation of this with illustrations on the page itself. A standard queue, on the other hand, even though doesn’t maintain the order of the messages, allows for more throughput of a queue. FIFO is used only in cases where the order of the messages is especially of significant importance. Also, FIFO is not available in all regions. For this example, we’ll stick to the standard queue.

Once you create a queue, you’ll see all the important details of the queue on the bottom half of the screen. One important information here is the SQS queue URL. It should look something similar to this:

https://sqs.us-east-2.amazonaws.com/1234/abcd

Make a note of this URL as we’ll be using this in our project to connect with the SQS service.


The Code

We’ll now start with the code. The first thing we need to add in our Spring Boot application is the SQS dependency. Fortunately, the dependency is available in the Maven central repository. So we just add the following in the dependencies block in our pom.xml file:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-aws-messaging</artifactId>
    <version>2.2.1.RELEASE</version>
</dependency>

Next, we have to take care of the properties. For this example, we’ll use the static credential provider for AWS. So we’ll need the access key and the secret key. I’ll assume that you already have these things. So I’ll skip instructions on how to set it up. In our application.properties file, we’ll have the following properties:

sqs.url=https://sqs.us-east-2.amazonaws.com/1234/abcd

aws.accessKey=
aws.secretKey=
aws.region=

Fill in the blanks in the properties file. We have to get these values in our Java code. Because we’re using Spring Boot, it’s very easy to get these values into our code, using the @Value annotation:

@Value("${sqs.url}")
private String sqsUrl;

@Value("${aws.accessKey}")
private String awsAccessKey;

@Value("${aws.secretKey}")
private String awsSecretKey;

@Value("${aws.region}")
private String awsRegion;

After this, we have to create an object for AWS credentails and one for SQS. We can do that using the code snippet below:

AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(
        new BasicAWSCredentials(awsAccessKey, awsSecretKey)
);

AmazonSQS amazonSQS = AmazonSQSClientBuilder.standard().withCredentials(awsCredentialsProvider).build();

The amazonSQS object we created here is what we’ll be using from now on. Now, to send a message, all you have to do is call the sendMessage() method on the SQS object, like this:

SendMessageResult result = amazonSQS.sendMessage(this.sqsUrl, message);

As you can guess, the first parameter is the URL of the SQS queue to which we’re sending the message, the second parameter is the actual message. I have written the SQS related code is a class called SQSUtil. This class is annotated as a @Component, so that I can @Autowire it anywhere in the code base. The class looks like this:

@Component
public class SQSUtil {

    @Value("${sqs.url}")
    private String sqsUrl;

    @Value("${aws.accessKey}")
    private String awsAccessKey;

    @Value("${aws.secretKey}")
    private String awsSecretKey;

    @Value("${aws.region}")
    private String awsRegion;

    private AmazonSQS amazonSQS;

    private static final Logger logger = LoggerFactory.getLogger(SQSUtil.class);

    @PostConstruct
    private void postConstructor() {

        logger.info("SQS URL: " + sqsUrl);

        AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(
                new BasicAWSCredentials(awsAccessKey, awsSecretKey)
        );

        this.amazonSQS = AmazonSQSClientBuilder.standard().withCredentials(awsCredentialsProvider).build();
    }

    public void sendSQSMessage(String message) {

        logger.info("Sending SQS message: " + message);

        SendMessageResult result = this.amazonSQS.sendMessage(this.sqsUrl, message);

        logger.info("SQS Message ID: " + result.getMessageId());
    }
}

Now let’s see how I’m using this. In the main class, I have autowired this utility class, like so:

@Autowired
private SQSUtil sqsUtil;

The message is a JSON string. But how do I create this JSON string? I created a simple POJO class for that. I created a few instances of this POJO class and used the Gson library to convert that POJO to JSON string. Let’s first look at the POJO class:

public class SamsungPhone {

    private String name;
    private String description;
    private long timestamp;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
}

I agree, it’s very simple and it makes no sense at all. Anyway, I created the following objects with this class:

List<SamsungPhone> samsungPhones = new ArrayList<>();

SamsungPhone galaxyNote10Plus = new SamsungPhone();
galaxyNote10Plus.setName("Samsung Galaxy Note 10 Plus");;
galaxyNote10Plus.setDescription("2019 flagship phone with a 6.8 inch Super AMOLED display, S Pen, and much more");
galaxyNote10Plus.setTimestamp(System.currentTimeMillis());
samsungPhones.add(galaxyNote10Plus);

SamsungPhone galaxyNote10 = new SamsungPhone();
galaxyNote10.setName("Samsung Galaxy Note 10");;
galaxyNote10.setDescription("2019 flagship phone with a 6.5 inch Super AMOLED display, S Pen, and much more");
galaxyNote10.setTimestamp(System.currentTimeMillis());
samsungPhones.add(galaxyNote10);

SamsungPhone galaxyS10Plus = new SamsungPhone();
galaxyS10Plus.setName("Samsung Galaxy S 10 Plus");;
galaxyS10Plus.setDescription("Early 2019 flagship phone with a 6.5 inch Super AMOLED display, " +
        "dual punch hole selfie cameras, and much more");
galaxyS10Plus.setTimestamp(System.currentTimeMillis());
samsungPhones.add(galaxyS10Plus);

SamsungPhone galaxyS10 = new SamsungPhone();
galaxyS10.setName("Samsung Galaxy S 10");;
galaxyS10.setDescription("Early 2019 flagship phone with a 6.3 inch Super AMOLED display, " +
        "dual punch hole selfie cameras, and much more");
galaxyS10.setTimestamp(System.currentTimeMillis());
samsungPhones.add(galaxyS10);

As you can see, I’m adding these objects to a list. I’m looping through that list, converting the object in each iteration to a JSON string, and calling the sendSQSMessage() method in the SQSUtil class to send it out to the SQS queue. Let’s look at that part of the code now:

for (SamsungPhone samsungPhone : samsungPhones) {
    this.sqsUtil.sendSQSMessage(new Gson().toJson(samsungPhone));
}

That wasn’t difficult at all, was it now?


In the next post, we’ll see how we can receive or consume the messages we just sent across. If you’re curious and want to see how different the code is for an Apache Kafka producer and consumer, check out this post, where I talk about the same. And if you want to dive deep into the code for this SQS example, head over to my Github repo, where you’ll get the working project for this example.

And if you like what you see here, or on my Medium blog, and would like to see more of such helpful technical posts in the future, consider supporting me on Patreon.

Become a Patron!

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: