Russell Bateman
July 2014
last update:
Here's a great tool, Nevado, for making the port of your JMS messaging layer to Amazon SQS (or even Comcast CMB) go easier. I'm corralling all the details here. I used ObjectAid to generate some light UML; here's the legend.
I need to look at this project to see if it's promising as a JMS abstraction of Amazon SQS for our use. What I've found so far is:
Here is a high-level diagram of Nevado's sessions, connections showing also Amazon SQS connectors.
Nevado's Amazon SQS connectors, queues and messages.
|
|
Nevado's Amazon SQS connector factories.
Last, for what it's worth, Nevado's mocking framework for testing purposes.
Got the Sun JMS example running using Nevado atop AWS SQS. I created an Eclipse project. I needed a properties file to solve AWS configuration. These values here are dummies that look a little bit like what you'd see, but are of no actual value.
access.key.id = AKIAIK7CONYFPBM2WKXQ access.secret.key = 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 queue.url = https://sqs.us-east-1.amazonaws.com/633002655422/acme-accounts
The JAR libraries I used I quickly found, mostly from Maven sites:
Here's the sample code. Highlighting are those lines which are necessarily Nevado while the rest of what's going on is pure JMS.
import java.net.URL;
import java.util.ResourceBundle;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.skyscreamer.nevado.jms.NevadoConnectionFactory;
import org.skyscreamer.nevado.jms.connector.amazonaws.AmazonAwsSQSConnectorFactory;
import org.skyscreamer.nevado.jms.destination.NevadoQueue;
public class HelloWorldMessage
{
public static void main( String[] args ) throws Exception
{
ResourceBundle bundle = ResourceBundle.getBundle( "resources/aws" );
String accessKey = bundle.getString( "access.key.id" );
String secretKey = bundle.getString( "access.secret.key" );
String queueUrl = bundle.getString( "queue.url" );
try
{
// Step 1: Create an Amazon AWS SQS connector factory for use in priming the pump.
// this step is not part of the Sun example.
AmazonAwsSQSConnectorFactory awsConnectorFactory = new AmazonAwsSQSConnectorFactory();
// Step 2: Instantiate an Amazon or Nevado connection factory, injecting AWS credentials.
// This step replaces this line in the Sun example:
// connectionFactory = new com.sun.messaging.ConnectionFactory();
ConnectionFactory connectionFactory = new NevadoConnectionFactory();
( ( NevadoConnectionFactory ) connectionFactory ).setSqsConnectorFactory( awsConnectorFactory );
( ( NevadoConnectionFactory ) connectionFactory ).setAwsAccessKey( accessKey );
( ( NevadoConnectionFactory ) connectionFactory ).setAwsSecretKey( secretKey );
// Step 3: Create a connection to Amazon SQS.
Connection connection = connectionFactory.createConnection();
// Step 4: Create a session from the connection.
Session session = connection.createSession( false, Session.AUTO_ACKNOWLEDGE );
// Step 5: Instantiate a new JMS queue using a Nevado queue, injecting AWS queue URL.
// This step replaces this line in the Sun example:
// queue = new com.sun.messaging.Queue( "world" );
Queue queue = new NevadoQueue( new URL( queueUrl ) );
// Step 6: Create a message producer.
MessageProducer producer = session.createProducer( queue );
// Step 7: Create and send a test message to the queue.
TextMessage sendingTextMessage = session.createTextMessage();
sendingTextMessage.setText( "Hello World" );
System.out.println( "Sending Message: " + sendingTextMessage.getText() );
producer.send( sendingTextMessage );
// Step 8: Create a message consumer.
MessageConsumer consumer = session.createConsumer( queue );
// Step 9: Start the connection (created in step 3).
connection.start();
// Step 10: Receive a message from the queue.
Message message = consumer.receive();
// Step 11: Retrieve the contents of the message.
if( message instanceof TextMessage )
{
TextMessage receivingTextMessage = ( TextMessage ) message;
System.out.println( "Read Message: " + receivingTextMessage.getText() );
}
/* --------------------------------------------------------------------------------
* Output should appear something like this:
*
* Sending Message: Hello World
* Jul 22, 2014 10:39:11 AM org.skyscreamer.nevado.jms.connector.amazonaws.AmazonAwsSQSConnector sendMessage
* INFO: Sent message to SQS f174ad51-994e-485f-91d6-578d8943b48e
* Jul 22, 2014 10:39:11 AM org.skyscreamer.nevado.jms.connector.amazonaws.AmazonAwsSQSConnector receiveMessage
* INFO: Received message f174ad51-994e-485f-91d6-578d8943b48e
* Read Message: Hello World
* --------------------------------------------------------------------------------
*/
// Step 12: Close the session and connection.
session.close();
connection.close();
}
catch( Exception e )
{
System.out.println( "Exception occurred : " + e.toString() );
e.printStackTrace();
}
}
}
From the sample code that now works, the essence of what we've learned about the JMS lifecycle is this:
In case I haven't flogged this horse enough, here's a diagram of the above sample. The special, Nevado classes are marked in grey, but everything else is pure JMS.