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)
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).
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>
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();
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);
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 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.
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
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>
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());
}
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);
}
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;
}
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.
When will it be possible to verify with actual SQS?
Recommended Posts