Description
The example shows how to use SQS (Amazon Simple Queue Service) queues in a Spring boot application – configuring the application to work with LocalStack, sending messages to the queue and downloading messages from the queue both in the application and using command line commands provided by AWS.
Requirements
- JDK 17+
- Spring-Boot 3.1.6
- LocalStack
Two Types of Queues:
1. Standard Queues: Amazon SQS offers standard as the default queue type. Standard queues support a nearly unlimited number of API calls per second, per API action (SendMessage, ReceiveMessage, or DeleteMessage). Standard queues support at-least-once message delivery. However, occasionally (because of the highly distributed architecture that allows nearly unlimited throughput), more than one copy of a message might be delivered out of order.
2. FIFO Queues: FIFO (First-In-First-Out) queues have all the capabilities of the standard queues, but are designed to enhance messaging between applications when the order of operations and events is critical, or where duplicates can’t be tolerated.
Creating Queues (LocalStack)
Start LocalStack
Create Queues
awslocal sqs create-queue --queue-name outcoming_messages_queue --region us-east-1 --endpoint-url http://localhost:4566
awslocal sqs create-queue --queue-name incoming_messages_queue --region us-east-1 --endpoint-url http://localhost:4566
awslocal sqs send-message --message-body "test-sending-01" --queue-url "http://localhost:4566/000000000000/incoming_messages_queue" --region us-east-1 --endpoint-url http://localhost:4566

Project Structure

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>zjc.examples</groupId>
<artifactId>sqs</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Demo project for SQS, Spring Boot and LocalStack</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.939</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>amazon-sqs-java-messaging-lib</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
outcoming.queue.name=outcoming_messages_queue
incoming.queue.name=incoming_messages_queueAppConfig.java
package zjc.examples.sqs.config;
import com.amazon.sqs.javamessaging.ProviderConfiguration;
import com.amazon.sqs.javamessaging.SQSConnectionFactory;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.sqs.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;
import org.springframework.jms.support.destination.DynamicDestinationResolver;
import zjc.examples.sqs.domain.MessageConsumer;
import zjc.examples.sqs.domain.MessageProducer;
import zjc.examples.sqs.receivers.JMSMessageListener;
import zjc.examples.sqs.senders.JMSMessageSender;
import javax.jms.Session;
@Configuration
@EnableJms
public class AppConfig {
@Value("${outcoming.queue.name}")
private String outcomingQueueName;
@Bean
public SQSConnectionFactory connectionFactory() {
AmazonSQSAsync build = AmazonSQSAsyncClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("xxx", "yyy")))
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://localhost:4566", "us-east-1"))
.build();
return new SQSConnectionFactory(new ProviderConfiguration(), build);
}
@Bean
public MessageConverter mappingJackson2MessageConverter() {
MappingJackson2MessageConverter jackson2MessageConverter = new MappingJackson2MessageConverter();
jackson2MessageConverter.setTargetType(MessageType.TEXT);
jackson2MessageConverter.setTypeIdPropertyName("_type");
return jackson2MessageConverter;
}
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(SQSConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setDestinationResolver(new DynamicDestinationResolver());
factory.setConcurrency("3-10");
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
return factory;
}
@Bean
public JmsTemplate jmsTemplate(SQSConnectionFactory connectionFactory) {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
jmsTemplate.setMessageConverter(mappingJackson2MessageConverter());
return jmsTemplate;
}
@Bean
public MessageProducer messageProducer(JmsTemplate jmsTemplate) {
return new MessageProducer(new JMSMessageSender(jmsTemplate, outcomingQueueName));
}
@Bean
public MessageConsumer messageConsumer() {
return new MessageConsumer();
}
@Bean
public JMSMessageListener jmsMessageListener() {
return new JMSMessageListener(messageConsumer());
}
}See at above:
@Bean
public SQSConnectionFactory connectionFactory() {
AmazonSQSAsync build = AmazonSQSAsyncClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("xxx", "yyy")))
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://localhost:4566", "us-east-1"))
.build();
return new SQSConnectionFactory(new ProviderConfiguration(), build);
}
region: “us-east-1” – set your
real aws credentials are not required: new BasicAWSCredentials(“xxx”, “yyy”)
MessageController.java
package zjc.examples.sqs.webaccess;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import zjc.examples.sqs.domain.Message;
import zjc.examples.sqs.domain.MessageConsumer;
import zjc.examples.sqs.domain.MessageProducer;
@RestController
public class MessageController {
private final MessageConsumer messageConsumer;
private final MessageProducer messageProducer;
public MessageController(MessageConsumer messageConsumer, MessageProducer messageProducer) {
this.messageConsumer = messageConsumer;
this.messageProducer = messageProducer;
}
@GetMapping("/last-message")
Message getLastMessage() {
return messageConsumer.getLastReceivedMessage();
}
@PostMapping("/send-message/{text}")
String sendMessage(@PathVariable String text) {
messageProducer.sendMessage(text);
return "message " + text + " sent";
}
}Run Spring-Boot.
If you did Create Queues you should be able to see:

Send Message
Postman:

https://localhost.localstack.cloud:4566:

–
Source Code: https://github.com/ZbCiok/zjc-examples/tree/main/aws/spring-boot/sqs-spring-boot-localstack
