Java is a popular platform for cloud applications that use Amazon Web Services.
With the AWS Java SDK, Java developers can build applications that work with various AWS services, like Simple Email Service (SES), Simple Queue Service (SQS), Simple Notification Service (SNS), and more.
Simple Email Service (SES) is a cloud-based email-sending service that enables developers to integrate email functionality into their applications running on AWS.
SES allows developers to work without an on-prem Simple Mail Transfer Protocol (SMTP) system and send bulk emails to many recipients.
LocalStack for AWS supports SES along with a simple user interface to inspect email accounts and sent messages.
LocalStack also supports sending SES messages through an actual SMTP email server.
We will use SQS and SNS to process the emails.
We would further employ a CloudFormation stack to configure the infrastructure and configure SNS & SQS subscriptions.
AWS Java SDK would be employed to receive these SQS messages and to send these messages through SES further.
In this tutorial, we will build a Java Spring Boot application that uses locally emulated AWS infrastructure on LocalStack provisioned by CloudFormation, and that uses the Java AWS SDK to send SES, SQS, and SNS messages.
We will further use MailHog, a local SMTP server, to inspect the emails sent through SES via an intuitive user interface.
To get started, we will set up our Spring Boot project by implementing a single module named example that will house our application code.
The module will contain the code required to set up our AWS configuration, notification service, and message application.
We will have another directory called resources that will house our CloudFormation stack required to set up an SNS topic and an SQS queue.
The project directory would look like this:
Terminal window
├──pom.xml
├──src
│└──main
│├──java
││└──com
││└──example
││├──AwsConfiguration.java
││├──MessageApplication.java
││├──Notification.java
││├──NotificationController.java
││└──ReceiveSendNotifications.java
│└──resources
│└──email-infra.yml
In our root POM configuration, we will add the following dependencies:
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>11</java.version>
<awsjavasdk.version>2.17.189</awsjavasdk.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.17.189</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>ses</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sns</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sqs</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>cloudformation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
In the above POM file, we have added the AWS Java SDK dependencies for SES, SNS, SQS, and CloudFormation.
We have also added the Spring Boot dependencies for our application.
We can move on to the next step with the initial setup complete.
To get started, we will setup the AWS configuration, to be defined in AwsConfiguration.java, required for our Spring Boot application.
We will create a configuration class to use the Spring Bean annotation to create two beans: SesClient and a SqsClient, to connect to the SES and SQS clients respectively.
We will then create a bean to retrieve the queueUrl for the email-notification-queue:
In the above code, we have used the @Autowired annotation to autowire the dependencies that are required for the application (SqsClientSesClient, and notificationQueueUrl in this case).
Now that we have got the URL of the queue created in the previous step, we can move on to the next step.
To get started with creating a Notification Service, we would need to create a Notification class to define the structure of the notification that we would be sending to the SQS queue.
We will create a Notification class in the Notification.java file:
packagecom.example;
publicclassNotification{
privateString address;
privateString subject;
privateString body;
publicStringgetAddress(){
return address;
}
publicvoidsetAddress(Stringaddress){
this.address= address;
}
publicStringgetSubject(){
return subject;
}
publicvoidsetSubject(Stringsubject){
this.subject= subject;
}
publicStringgetBody(){
return body;
}
publicvoidsetBody(Stringbody){
this.body= body;
}
}
In the above code, we have defined three instance variables: address, subject, and body.
We have also defined the getters and setters for the instance variables.
Let’s now create a @Component class to listen to a queue, receive and transform the notifications into emails, and send the emails transactionally:
Now that we have the code ready, let us setup the Spring Boot application using the SpringApplication Class to bootstrap and launch our Spring application from the main method.
You can now build the application using the following command:
Terminal window
mvncleaninstall
If the build is successful, you will notice a BUILD SUCCESS message.
Now that we have the application ready, let us setup the infrastructure using CloudFormation.
Create a new file in ``src/main/resourcescalledemail-infra.yml` and add the following content:
AWSTemplateFormatVersion: 2010-09-09
Resources:
EmailQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: email-notification-queue
EmailTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: email-notifications
SnsSubscription:
Type: AWS::SNS::Subscription
Properties:
Protocol: sqs
Endpoint: !GetAttEmailQueue.Arn
TopicArn: !GetAttEmailTopic.TopicArn
In the above code, we have created a queue called email-notification-queue and a topic called email-notifications.
We have also created a subscription between the queue and the topic, allowing any message published to the topic to be sent to the queue.
Now that the initial coding is done, we can give it a try.
Let’s start LocalStack using a custom docker-compose setup, which includes MailHog to capture the emails sent by SES:
The above docker-compose file will start LocalStack and pull the MailHog image to start the SMTP server (if it doesn’t exist yet!) on port 8025.
You can start LocalStack using the following command:
With our infrastructure ready, we can now start the Spring Boot application.
We will set dummy AWS access credentials as environment variables in the command:
In the above command, we have published a message to the topic email-notifications with a generic message body.
The output of the command should look like this:
{
"MessageId": "<MESSAGE-ID>"
}
You can now use curl to send a request to the /list endpoint for the queued messages:
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.