Develop a Java application that uses Amazon SQS (Part 2)

About this article

It is a continuation of the following article. We will continue to introduce the development of Java applications that access Amazon SQS. For the environment, use Elastic MQ container instead of SQS, and use the created standard queue as the queue.

Developing a Java application that uses Amazon SQS (Part 1)

Use of JMS

In the previous article, SQS access was performed using the AWS SDK, but when you think of messaging in Java, you may think of the standard specification JMS (Java Messaging Service). For JMS, the Amazon SQS Java Messaging Library is provided for SQS, so I will show you how to access SQS using it. This library makes SQS available to existing JMS applications with minimal changes.

Using JMS and Amazon SQS-Amazon Simple Queue Service (https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-java-message-service-jms-client.html)

Please note that the library support is limited to a part of JMS1.1 (message transmission / reception in the point-to-point model).

Preparation

To take advantage of the Amazon SQS Java Messaging Library, you need to add library dependencies along with the SDK. When using Maven, please define as follows in pom.xml.

        <dependency>
		  <groupId>software.amazon.awssdk</groupId>
		  <artifactId>sqs</artifactId>
		</dependency>
		<dependency>
		  <groupId>com.amazonaws</groupId>
		  <artifactId>amazon-sqs-java-messaging-lib</artifactId>
		  <version>1.0.4</version>
		  <type>jar</type>
		</dependency>

Connection to SQS (Elastic MQ)

Use the Library-provided ConnectionFactory to connect to SQS. Since we are using an Elastic MQ container this time, we need to overwrite the endpoint URL as in the previous article. It also uses a different client builder than connecting directly with the SDK.

The code example from here is based on the following. Example of using Java with Amazon SQS standard queues using JMS

    AmazonSQSClientBuilder builder = AmazonSQSClientBuilder.standard();
    builder.setEndpointConfiguration(new EndpointConfiguration("http://localhost:9324", "us-east-1"));
    
    SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
            new ProviderConfiguration(),
            builder
            );
     
    SQSConnection connection = connectionFactory.createConnection();

Send message from session establishment

You can send and receive messages by establishing a JMS session after connecting. From this point onward, the JMS standard interface will be used. The following is a code example for sending a message.

    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    Queue queue = session.createQueue("testqueue");

    MessageProducer producer = session.createProducer(queue);
    TextMessage message = session.createTextMessage("Hello World!");
    producer.send(message);

Receive message

The message reception is implemented as follows.

    Message receivedMessage = consumer.receive(1000);
 
    if (receivedMessage != null) {
        System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
    }

Asynchronous reception of messages by JMS listeners is also possible.

    MessageConsumer consumer = session.createConsumer(queue);   
    consumer.setMessageListener(new MyListener());    
    connection.start();

MyListener.java


public class MyListener implements MessageListener {

  @Override
  public void onMessage(Message message) {
     //Process message
  }

}

Disconnect from SQS

Disconnect as in the case of SDK.

    connection.close();

This is the end of SQS access by JMS. If you are familiar with JMS, you will find that it can be used with a similar implementation.

Use of Spring JMS

The standard is JMS, but recently there should be many people who are developing using Spring Boot or Spring JMS, so finally I will introduce the access method when using these.

Here, I referred to the contents of the link below. Developing messaging system with Spring Boot, JMS and AWS SQS

Preparation

Here, add the dependency of Spring-JMS and Spring boot starter to pom.xml. There are various components in Spring, but if you want to operate the following code examples, add the following contents to the definition so far.

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
             <groupId>org.springframework</groupId>
             <artifactId>spring-jms</artifactId>
             <version>5.1.4.RELEASE</version>
        </dependency>

Connection to SQS (Elastic MQ)

Spring Boot allows you to implement bean definitions in Java, so implement the Config class to enable Spring JMS. Spring JMS is enabled by adding the EnableJms annotation. It also creates a ConnectionFactory (the content is the same as for JMS) and implements the Bean definition of JmsTemplate that uses it.

@EnableJms
@Configuration
public class JmsConfig {
  
    public SQSConnectionFactory sqsConnectionFactory() {

        AmazonSQSClientBuilder builder = AmazonSQSClientBuilder.standard();
        builder.setEndpointConfiguration(new EndpointConfiguration("http://localhost:9324", "us-east-1"));
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                builder
                );
        return connectionFactory;
    }

     @Bean
     public JmsTemplate defaultJmsTemplate() {
         return new JmsTemplate(sqsConnectionFactory());
     }

Send a message using JmsTemplate

By injecting the JmsTemplate defined in the Config class, the class that sends and receives messages does not need to be aware of the connection to SQS. JmsTemplate is a Template class for sending and receiving messages provided by Spring JMS, and it can be implemented very easily if it is a simple sending and receiving process.

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

Receive message

Spring JMS allows you to implement message-driven POJOs called MDPs (Message-Driven POJOs). The following is a code example of receiving a message by MDP. By adding the JmsListener annotation, when a message enters the queue specified in the destination attribute, it will be received and the method processing will be called.

  @JmsListener(destination="testqueue")
  public void receive(TextMessage message) {
    System.out.println("received: "+message);
  }

In order to use MDP, it is necessary to implement the following Bean definition of ListenerContainerFactory in Config class.

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

Disconnect from SQS

Spring does it internally, so you don't have to be aware of it in your application.


You can see that you can access SQS in a fairly simple way by using Spring JMS. When using Elastic MQ as an alternative to SQS, I am concerned that it is necessary to overwrite the endpoint URL for connection, but if you use Spring's Profile function etc. well, you can switch between environments smartly. I think it is.

At the end

When will it be possible to verify with actual SQS?

Recommended Posts

Develop a Java application that uses Amazon SQS (Part 1)
Develop a Java application that uses Amazon SQS (Part 2)
A bat file that uses Java in windows
How to implement a job that uses Java API in JobScheduler
Access Teradata from a Java application
Build a web application development environment that uses Java, MySQL, and Redis with Docker CE for Windows
Creating a java web application development environment with docker for mac part1
Create a java web application development environment with docker for mac part2
[Java] Implement a function that uses a class implemented in the Builder pattern
I want to develop a web application!
Connect to Aurora (MySQL) from a Java application
[Ruby] A program that uses search and each_with_index
CICS-Run Java application-(1) Run a simple sample app