Using the Amazon SQS Java Messaging Library
To get started using the Java Message Service (JMS) with Amazon SQS, use the code examples in this section. The following sections show how to create a JMS connection and a session, and how to send and receive a message.
The wrapped Amazon SQS client object included in the Amazon SQS Java Messaging Library checks if an Amazon SQS queue exists. If the queue doesn't exist, the client creates it.
Creating a JMS connection
Before you begin, see the prerequisites in Prerequisites for working with JMS and Amazon SQS.
-
Create a connection factory and call the
createConnectionmethod against the factory.// Create a new connection factory with all defaults (credentials and region) set automatically SQSConnectionFactory connectionFactory = new SQSConnectionFactory( new ProviderConfiguration(), AmazonSQSClientBuilder.defaultClient() ); // Create the connection. SQSConnection connection = connectionFactory.createConnection();The
SQSConnectionclass extendsjavax.jms.Connection. Together with the JMS standard connection methods,SQSConnectionoffers additional methods, such asgetAmazonSQSClientandgetWrappedAmazonSQSClient. Both methods let you perform administrative operations not included in the JMS specification, such as creating new queues. However, thegetWrappedAmazonSQSClientmethod also provides a wrapped version of the Amazon SQS client used by the current connection. The wrapper transforms every exception from the client into anJMSException, allowing it to be more easily used by existing code that expectsJMSExceptionoccurrences. -
You can use the client objects returned from
getAmazonSQSClientandgetWrappedAmazonSQSClientto perform administrative operations not included in the JMS specification (for example, you can create an Amazon SQS queue).If you have existing code that expects JMS exceptions, then you should use
getWrappedAmazonSQSClient:-
If you use
getWrappedAmazonSQSClient, the returned client object transforms all exceptions into JMS exceptions. -
If you use
getAmazonSQSClient, the exceptions are all Amazon SQS exceptions.
-
Creating an Amazon SQS queue
The wrapped client object checks if an Amazon SQS queue exists.
If a queue doesn't exist, the client creates it. If the queue does exist, the function doesn't return anything. For more information, see the "Create the queue if needed" section in the TextMessageSender.java example.
To create a standard queue
// Get the wrapped client AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient(); // Create an SQS queue named MyQueue, if it doesn't already exist if (!client.queueExists("MyQueue")) { client.createQueue("MyQueue"); }
To create a FIFO queue
// Get the wrapped client AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient(); // Create an Amazon SQS FIFO queue named MyQueue.fifo, if it doesn't already exist if (!client.queueExists("MyQueue.fifo")) { Map<String, String> attributes = new HashMap<String, String>(); attributes.put("FifoQueue", "true"); attributes.put("ContentBasedDeduplication", "true"); client.createQueue(new CreateQueueRequest().withQueueName("MyQueue.fifo").withAttributes(attributes)); }
Note
The name of a FIFO queue must end with the .fifo suffix.
For more information about the ContentBasedDeduplication
attribute, see Exactly-once processing in
Amazon SQS.
Sending messages synchronously
-
When the connection and the underlying Amazon SQS queue are ready, create a nontransacted JMS session with
AUTO_ACKNOWLEDGEmode.// Create the nontransacted session with AUTO_ACKNOWLEDGE mode Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); -
To send a text message to the queue, create a JMS queue identity and a message producer.
// Create a queue identity and specify the queue name to the session Queue queue = session.createQueue("MyQueue"); // Create a producer for the 'MyQueue' MessageProducer producer = session.createProducer(queue); -
Create a text message and send it to the queue.
-
To send a message to a standard queue, you don't need to set any additional parameters.
// Create the text message TextMessage message = session.createTextMessage("Hello World!"); // Send the message producer.send(message); System.out.println("JMS Message " + message.getJMSMessageID()); -
To send a message to a FIFO queue, you must set the message group ID. You can also set a message deduplication ID. For more information, see Amazon SQS FIFO queue key terms.
// Create the text message TextMessage message = session.createTextMessage("Hello World!"); // Set the message group ID message.setStringProperty("JMSXGroupID", "Default"); // You can also set a custom message deduplication ID // message.setStringProperty("JMS_SQS_DeduplicationId", "hello"); // Here, it's not needed because content-based deduplication is enabled for the queue // Send the message producer.send(message); System.out.println("JMS Message " + message.getJMSMessageID()); System.out.println("JMS Message Sequence Number " + message.getStringProperty("JMS_SQS_SequenceNumber"));
-
Receiving messages synchronously
-
To receive messages, create a consumer for the same queue and invoke the
startmethod.You can call the
startmethod on the connection at any time. However, the consumer doesn't begin to receive messages until you call it.// Create a consumer for the 'MyQueue' MessageConsumer consumer = session.createConsumer(queue); // Start receiving incoming messages connection.start(); -
Call the
receivemethod on the consumer with a timeout set to 1 second, and then print the contents of the received message.-
After receiving a message from a standard queue, you can access the contents of the message.
// Receive a message from 'MyQueue' and wait up to 1 second Message receivedMessage = consumer.receive(1000); // Cast the received message as TextMessage and display the text if (receivedMessage != null) { System.out.println("Received: " + ((TextMessage) receivedMessage).getText()); } -
After receiving a message from a FIFO queue, you can access the contents of the message and other, FIFO-specific message attributes, such as the message group ID, message deduplication ID, and sequence number. For more information, see Amazon SQS FIFO queue key terms.
// Receive a message from 'MyQueue' and wait up to 1 second Message receivedMessage = consumer.receive(1000); // Cast the received message as TextMessage and display the text if (receivedMessage != null) { System.out.println("Received: " + ((TextMessage) receivedMessage).getText()); System.out.println("Group id: " + receivedMessage.getStringProperty("JMSXGroupID")); System.out.println("Message deduplication id: " + receivedMessage.getStringProperty("JMS_SQS_DeduplicationId")); System.out.println("Message sequence number: " + receivedMessage.getStringProperty("JMS_SQS_SequenceNumber")); }
-
-
Close the connection and the session.
// Close the connection (and the session). connection.close();
The output looks similar to the following:
JMS Message ID:8example-588b-44e5-bbcf-d816example2
Received: Hello World!
Note
You can use the Spring Framework to initialize these objects.
For additional information, see SpringExampleConfiguration.xml,
SpringExample.java, and the other helper classes in
ExampleConfiguration.java and ExampleCommon.java in
the Working Java examples for using JMS with Amazon SQS
standard queues
section.
For complete examples of sending and receiving objects, see TextMessageSender.java and SyncMessageReceiver.java.
Receiving messages asynchronously
In the example in Using the Amazon SQS Java Messaging Library, a
message is sent to MyQueue and received synchronously.
The following example shows how to receive the messages asynchronously through a listener.
-
Implement the
MessageListenerinterface.class MyListener implements MessageListener { @Override public void onMessage(Message message) { try { // Cast the received message as TextMessage and print the text to screen. System.out.println("Received: " + ((TextMessage) message).getText()); } catch (JMSException e) { e.printStackTrace(); } } }The
onMessagemethod of theMessageListenerinterface is called when you receive a message. In this listener implementation, the text stored in the message is printed. -
Instead of explicitly calling the
receivemethod on the consumer, set the message listener of the consumer to an instance of theMyListenerimplementation. The main thread waits for one second.// Create a consumer for the 'MyQueue'. MessageConsumer consumer = session.createConsumer(queue); // Instantiate and set the message listener for the consumer. consumer.setMessageListener(new MyListener()); // Start receiving incoming messages. connection.start(); // Wait for 1 second. The listener onMessage() method is invoked when a message is received. Thread.sleep(1000);
The rest of the steps are identical to the ones in the Using the Amazon SQS Java Messaging Library example. For a complete example of an asynchronous
consumer, see AsyncMessageReceiver.java in Working Java examples for using JMS with Amazon SQS
standard queues.
The output for this example looks similar to the following:
JMS Message ID:8example-588b-44e5-bbcf-d816example2
Received: Hello World!
Using client acknowledge mode
The example in Using the Amazon SQS Java Messaging Library uses
AUTO_ACKNOWLEDGE mode where every received message is acknowledged
automatically (and therefore deleted from the underlying Amazon SQS queue).
-
To explicitly acknowledge the messages after they're processed, you must create the session with
CLIENT_ACKNOWLEDGEmode.// Create the non-transacted session with CLIENT_ACKNOWLEDGE mode. Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); -
When the message is received, display it and then explicitly acknowledge it.
// Cast the received message as TextMessage and print the text to screen. Also acknowledge the message. if (receivedMessage != null) { System.out.println("Received: " + ((TextMessage) receivedMessage).getText()); receivedMessage.acknowledge(); System.out.println("Acknowledged: " + message.getJMSMessageID()); }Note
In this mode, when a message is acknowledged, all messages received before this message are implicitly acknowledged as well. For example, if 10 messages are received, and only the 10th message is acknowledged (in the order the messages are received), then all of the previous nine messages are also acknowledged.
The rest of the steps are identical to the ones in the Using the Amazon SQS Java Messaging Library example. For a complete example of a synchronous
consumer with client acknowledge mode, see
SyncMessageReceiverClientAcknowledge.java in Working Java examples for using JMS with Amazon SQS
standard queues.
The output for this example looks similar to the following:
JMS Message ID:4example-aa0e-403f-b6df-5e02example5
Received: Hello World!
Acknowledged: ID:4example-aa0e-403f-b6df-5e02example5
Using unordered acknowledge mode
When using CLIENT_ACKNOWLEDGE mode, all messages received before an
explicitly-acknowledged message are acknowledged automatically. For more information,
see Using client acknowledge mode.
The Amazon SQS Java Messaging Library provides another acknowledgement mode. When
using UNORDERED_ACKNOWLEDGE mode, all received messages must be
individually and explicitly acknowledged by the client, regardless of their reception
order. To do this, create a session with UNORDERED_ACKNOWLEDGE mode.
// Create the non-transacted session with UNORDERED_ACKNOWLEDGE mode. Session session = connection.createSession(false, SQSSession.UNORDERED_ACKNOWLEDGE);
The remaining steps are identical to the ones in the Using client acknowledge mode example. For a complete example of a
synchronous consumer with UNORDERED_ACKNOWLEDGE mode, see
SyncMessageReceiverUnorderedAcknowledge.java.
In this example, the output looks similar to the following:
JMS Message ID:dexample-73ad-4adb-bc6c-4357example7
Received: Hello World!
Acknowledged: ID:dexample-73ad-4adb-bc6c-4357example7