How to use Amazon Simple Queue Service in Play Framework
Amazon SQS (Simple Queue Service) is a distributed queue messaging service provided by Amazon. SQS is intended to provide a highly scalable hosted message queue that resolves issues arising from the common producer-consumer problem or connectivity between producer and consumer.
A message queue is a perfect tool to use to handle asynchronous work that you don’t want to perform in a web request. For example you might have a web requests that registers a new user in your application and you want to send an welcoming e-mail to the new user.
Sending e-mail is a slow and error prone process so you don’t want it to slow down your application. Instead you can just use a message queue and put a message on the queue in the web request and then let Akka do the sending of the e-mails in the background.
In this article I’m going to show you how to setup and integrate Amazon SQS in Play Framework.
Setup Amazon Web Services and SQS
First off, you need to sign up at Amazon Web Services if you don’t already have an account.
When you have an account ready and have logged in to Amazon Web Services you’ll see all the services that Amazon offers. Under the App Services section you’ll find SQS. Click on SQS and then click on Create New Queue. Just give your queue a name and save it.
Your new queue gets an unique URL that you need later to connect to the queue. Make sure to write it down:
Also make sure to visit the Security Credentials page and create an Access Key ID and Secret Access Key that we need later to connect to SQS.
Setup Play
Create a new Play project:
play new sqs
Then choose to create a simple Java application. After this you need to add AWS SDK for Java to your project.
build.sbt:
name := "sqs"
version := "1.0-SNAPSHOT"
libraryDependencies ++= Seq(
javaJdbc,
javaEbean,
cache,
"com.amazonaws" % "aws-java-sdk" % "1.7.1"
)
play.Project.playJavaSettings
Now you can run this command to resolve the dependencies:
play update
We also need to prepare our application with the necessary configuration needed to connect to Amazon SQS. Add the following configuration to the bottom of your conf/application.conf file:
## Amazon Credentials
aws.access.key = "ADD-YOUR-ACCESS-KEY-HERE"
aws.secret.key = "ADD-YOUR-SECRET-KEY-HERE"
## Amazon SQS configuration
aws.sqs.url="ADD-YOUR-SQS-QUEUE-URL-HERE"
aws.sqs.maxNumberOfMessages=2
Create the SQS Plugin
When I integrate stuff with third party services in Play I like to create a plugin. A Play plugin is a class that extends the Java class play.Plugin. This class may be something you have written in your own application, or it may be a plugin from a module. There are three methods that we can override – onStart(), onStop() and enabled(). To have some functionality occur when the application starts you can override onStart() and have something occur when the application starts we can override the onStop() method.
Create a new class named SQSPlugin
and put it under a plugins
package, and let it extend play.Plugin.
Here’s my implementation:
package plugins;
import java.util.List;
import play.*;
import com.amazonaws.auth.*;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.*;
public class SQSPlugin extends Plugin {
public static final String AWS_ACCESS_KEY = "aws.access.key";
public static final String AWS_SECRET_KEY = "aws.secret.key";
private final Application application;
private static AmazonSQSClient client;
public SQSPlugin(Application application) {
this.application = application;
}
public static void sendMessage(String queueUrl, String message) {
SendMessageRequest sendMsgReq = new SendMessageRequest(queueUrl, message);
client.sendMessage(sendMsgReq);
}
public static List<Message> receiveMessages(String queueUrl, int maxNumberOfMessages) {
ReceiveMessageRequest receiveMsgReq = new ReceiveMessageRequest(queueUrl);
receiveMsgReq.setMaxNumberOfMessages(maxNumberOfMessages);
ReceiveMessageResult result = client.receiveMessage(receiveMsgReq);
return result.getMessages();
}
public static void deleteMessage(String queueUrl, Message msg) {
DeleteMessageRequest delMsgRequest = new DeleteMessageRequest(queueUrl, msg.getReceiptHandle());
client.deleteMessage(delMsgRequest);
}
@Override
public void onStart() {
String accessKey = application.configuration().getString(AWS_ACCESS_KEY);
String secretKey = application.configuration().getString(AWS_SECRET_KEY);
if ((accessKey != null) && (secretKey != null)) {
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
client = new AmazonSQSClient(awsCredentials);
}
}
@Override
public boolean enabled() {
return (application.configuration().keys().contains(AWS_ACCESS_KEY) &&
application.configuration().keys().contains(AWS_SECRET_KEY));
}
}
So this class gives us some basic functionality to send a message to a specified queue, receive a list of messages so we can do something with them and also a method to delete a message from the queue.
To make the plugin startup when your application starts you have to create a play.plugins
file in the conf directory with the following content:
1501:plugins.SQSPlugin
Example usage
To demonstrate the usage of the functionality you can just use the existing Application controller in your application:
package controllers;
import java.util.List;
import com.amazonaws.services.sqs.model.Message;
import play.*;
import play.mvc.*;
import plugins.SQSPlugin;
import views.html.*;
public class Application extends Controller {
static Configuration config = Play.application().configuration();
static String QUEUE_URL = config.getString("aws.sqs.url");
static int MAX_MSG = config.getInt("aws.sqs.maxNumberOfMessages");
public static Result index() {
return ok(index.render("Your new application is ready."));
}
public static Result send() {
SQSPlugin.sendMessage(QUEUE_URL, "Hello World!");
return ok("Message sent.");
}
public static Result receive() {
String result = "";
List<Message> msgs = SQSPlugin.receiveMessages(QUEUE_URL, MAX_MSG);
for (Message msg : msgs) {
result = msg.getBody();
}
return ok(result);
}
}
Then add this to your conf/routes
file:
GET /send controllers.Application.send()
GET /receive controllers.Application.receive()
Start the Play server and point your browser at http://localhost:9000/send and then go to http://localhost:9000/receive and you should see Hello world.
Versions used in this article:
Play Framework 2.2.1
AWS Java SDK 1.7.1
Java 1.7.0_51