April 24, 2024

The ContactSunny Blog

Tech from one dev to another

Publishing messages to Amazon SNS from a Spring Boot application

5 min read
We'll learn how we can publish messages to an SNS topic from a Spring Boot application. This can be done from any Java code or framework.

In this post, we’ll see how we can publish messages to Amazon SNS, which stands for Simple Notification Service. If you’ve already read through my post about how to send messages to an SQS queue, you’ll see this post is quite similar to that. Because, thanks to Amazon, the clients have such similar signatures that you just change the class, and it all works as expected. But nonetheless, I’ll try to be thorough with the explanation here.

To begin, we first need to head over to the Amazon SNS home page on the AWS Console. Once you’re there, create an SNS topic, with a name of your choice. I chose the name ‘thetechcheck’ for obvious reasons. I’ll stick with that name for the post. Once you have that, take a copy of the topic ARN, which is what we’ll be using while publishing messages to the topic. Once you have these pre-requisites set, move on to the next section.


The Code

The Properties File

Before we go to the coding part, we’ll first get our configuration setup. For this POC, we’ll need the topic ARN, AWS credentials, and the topic region. We’ll keep these things in the application.properties file, as we’re building a Spring Boot project. My properties file looks like this:

sns.topic.arn=arn:aws:sns:us-east-1:123456789:thetechcheck

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

Obviously, you’ll have to fill in the blanks there for the credentials and the region. The ARN I have mentioned in the code block above is fake, and it is there only to represent how an ARN looks like.

Next, we’ll have to import these values into our class, and because we’re using Spring Boot, we can easily import these values using the @Value annotation, like this:

@Value("${sns.topic.arn}")
private String snsTopicARN;

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

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

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

The SNSUtil Utility Class for Amazon SNS operations

We’ll write a utility class named SNSUtil, which will be a @Component, and it will handle all SNS related operations. This is the class which will do the actual job of publishing messages to the Amazon SNS topic. So let’s begin this class with a @PostContruct hook, where we’ll initialise a few things:

@PostConstruct
private void postConstructor() {

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

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

    this.amazonSNS = AmazonSNSClientBuilder.standard()
            .withCredentials(awsCredentialsProvider)
            .withRegion(awsRegion)
            .build();
}

As you can see, we’re creating an instance of the AWSCredentialsProvider class, where we’re passing our AWS credentials. After that, we’re creating an Amazon SNS client using the provided builder. Make sure you provide the same region where you created the topic, otherwise it’ll not work, you’ll get a bad request exception. Next we need to look at how to publish a message. For this, I have written a simple wrapper method.

public void publishSNSMessage(String message) {

    logger.info("Publishing SNS message: " + message);

    PublishResult result = this.amazonSNS.publish(this.snsTopicARN, message);

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

As you can see from the code snippet above, the actual code for publishing a message is a one-liner. But I have added a couple of logs before and after just to make sure we have some logs to play with. Anyway, we’ll move on to the next section now.


The POJO Class

Because we need to publish some messages to the topic, I thought it would be good idea to publish a few JSON messages instead of just strings. The easiest way to generate JSON strings is by serialising an object with the Gson class. For this, we first need to have a class which can later be serialised. Similar to our previous example, I created a class called SamsungPhone. The whole class is as follows:

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;
    }
}

That was very simple.


Testing the Amazon SNS message publishing code

Now we’ll move on to our main class. Here, we’ll first @Autowire our utility class, like so:

@Autowired
private SNSUtil snsUtil;

Next, we’ll create a few instances of the POJO class we created earlier:

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 probably tell, this is same set of data from the SQS example, I just copied the same thing. Anyway, we now have a list of these objects. We’ll loop through the list, convert the objects to JSON strings using the Gson library, and publish them to SNS:

for (SamsungPhone samsungPhone : samsungPhones) {
    this.snsUtil.publishSNSMessage(new Gson().toJson(samsungPhone));
}

And that’s it.


Receiving these messages

The next obvious question would be, how do we receive these messages once we’ve published them? There are many ways in which you can subscribe to an SNS topic, one easiest way it to create a queue and subscribe that queue to the SNS topic. This way, whenever there is a message published to the SNS topic in question, that message will be automatically put into that SQS queue. You can write a simple SQS queue consumer to receive and process these messages. You can read my post about how to do that here. We’re done now. I’ve also written about how we can emulate Apache Kafka using exactly this method. You can read about that here.


If you want dive right into the finished, working project for this example instead of creating one for yourself, you can just fork my project from my Github repo.

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!

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.