Developing messaging system with Spring Boot, JMS and AWS SQS

This post provides a step by step description on how to configure Spring Boot to access AWS SQS via Spring JMS. I came across a few examples online but they seem to be a bit outdated since AWS updated its SDK and deprecated some of its classes/methods. The setup in this post is current as of today (May 2019).

Maven Setup

First, we need to pull in AWS Java SDK and SQS messaging library. I am using Spring Boot version 2.1.1 with the following AWS/SQS library versions:

<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jms</artifactId>
</dependency>
<dependency>
     <groupId>com.amazonaws</groupId>
     <artifactId>aws-java-sdk</artifactId>
     <version>1.11.549</version>
</dependency>
<dependency>
     <groupId>com.amazonaws</groupId>
     <artifactId>amazon-sqs-java-messaging-lib</artifactId>
     <version>1.0.6</version>
     <type>jar</type>
</dependency>

Spring Boot Configuration

Next, we need to setup Spring JMS configurations:

@EnableJms
@Configuration
public class JmsConfig {
        @Bean
	public ErrorHandler errorHandler() {
		return new JmsErrorHandler();
	}

	public SQSConnectionFactory sqsConnectionFactory() {
		AmazonSQS sqs = AmazonSQSClientBuilder.standard().withRegion(Regions.AP_SOUTHEAST_2).build();
		SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
		        new ProviderConfiguration(),
		        sqs
		        );
		return connectionFactory;
	}

        @Bean
        public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
             DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
             factory.setConnectionFactory(sqsConnectionFactory());
             factory.setDestinationResolver(new DynamicDestinationResolver());
             factory.setConcurrency("3-10");
             factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
             factory.setErrorHandler(errorHandler());
             return factory;
         }
    
         @Bean
         public JmsTemplate defaultJmsTemplate() {
    	     return new JmsTemplate(sqsConnectionFactory());
         }
}

The codes above set up a JMS connection factory for SQS (class SQSConnectionFactory). A listener container factory bean is configured to listen to messages from SQS queues. Similarly a JMS template bean is created to publish messages to SQS queues.

Note also the use of @EnableJms in the configuration above.

Receive messages from SQS

To receive message from SQS, annotate a method with @JmsListener:

@JmsListener(destination = "my_queue_name")
public void receive(String message) throws JMSException {
     logger.info("Received message {}", message);
     // do something useful with the message here
     ...
}

Publish messages to SQS

To publish JMS message to SQS, use the JmsTemplate configured above. For example

@Autowired
private JmsTemplate jmsTemplate;
...
public void sendToSQS(String destination, String message) {
     jmsTemplate.convertAndSend(destination, message);
}

That’s it. Now we have a complete set up to build interesting stuff with Spring Boot and SQS.