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.