Статьи

Использование AWS SQS в качестве JMS-провайдера со Spring

Недавно AWS опубликовал новую клиентскую библиотеку, которая реализует спецификацию JMS 1.1 и использует их Simple Queue Service (SQS) в качестве поставщика JMS (см. Пост Джеффа Барра здесь ). В моем посте я покажу вам, как настроить проект Maven для использования Spring Framework для использования этой библиотеки.
Мы выполним следующие шаги:

  • Создайте очередь в Консоли управления AWS
  • Настройте свои учетные данные AWS на своем компьютере
  • Настройте свой проект Maven
  • Создать конфигурацию Spring
  • Создание файлов Java для создания и получения сообщений.

Этот пост покажет только некоторые основные возможности использования SQS, но должен быть достаточно хорош для начала. Я предполагаю, что вы уже создали свою учетную запись AWS и знакомы с Maven и базовыми настройками Spring.

Создайте очередь в Консоли управления AWS

Первый шаг — создать очередь, чтобы мы могли использовать ее в нашей программе. Я покажу вам, как создать очередь с помощью консоли управления, но вы также можете создать необходимые очереди программным способом.

Когда вы переходите на консоль управления, вы можете выбрать страницу SQS и нажать кнопку «Создать новую очередь»:

скриншот-на-мар-28-20-10-00

Введите имя очереди и примите настройки по умолчанию, нажав кнопку «Создать очередь»:

скриншот-на-мар-28-20-10-59

Настройте свои учетные данные AWS на своем компьютере

Чтобы получить доступ к своим материалам AWS с помощью Java SDK, проще всего создать файл ‘credentials.proeprties’ в домашнем каталоге пользователя. Создайте файл учетных данных в ~ / .aws / credentials (C: \ Users \ USER_NAME \ .aws \ credentials для пользователей Windows) и сохраните следующие строки после замены заглавных значений своими.

1
2
3
[default]
aws_access_key_id = YOUR_ACCESS_KEY_ID
aws_secret_access_key = YOUR_SECRET_ACCESS_KEY

Настройте свой проект Maven

При использовании Maven для настройки вашего проекта вы можете добавить следующие зависимости в ваш pom, чтобы иметь возможность использовать AWS SQS с Spring 4:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?xml version="1.0" encoding="UTF-8"?>
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>net.pascalalma.aws</groupId>
    <artifactId>sqs-client</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <properties>
        <version.spring>4.1.5.RELEASE</version.spring>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${version.spring}</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>amazon-sqs-java-messaging-lib</artifactId>
            <version>1.0.0</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
</project>

Создать конфигурацию Spring

В первом примере я буду использовать простой класс MessageProducer и MessageConsumer, в котором производитель помещает сообщение в очередь, а потребитель читает одно сообщение из очереди. На эту модель AWS ссылается как на «синхронный» вызов. Конфигурация Spring выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="UTF-8"?>
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
 
    <context:component-scan base-package="net.pascalalma.aws.sqs"></context:component-scan>
 
    <bean id="credentialsProviderBean" class="com.amazonaws.auth.DefaultAWSCredentialsProviderChain"/>
 
    <bean id="connectionFactoryBuilder" class="com.amazon.sqs.javamessaging.SQSConnectionFactory$Builder">
        <property name="regionName" value="eu-west-1"/>
        <property name="numberOfMessagesToPrefetch" value="5"/>
        <property name="awsCredentialsProvider" ref="credentialsProviderBean"/>
    </bean>
 
    <bean id="connectionFactory" class="com.amazon.sqs.javamessaging.SQSConnectionFactory"
          factory-bean="connectionFactoryBuilder"
          factory-method="build"/>
 
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="defaultDestinationName" ref="queueName"/>
    </bean>
 
    <bean id="queueName" class="java.lang.String">
        <constructor-arg value="DefaultDemoQueue"/>
    </bean>
</beans>

Создание файлов Java для создания и получения сообщений.

Последний шаг — создание необходимых файлов Java. Я думаю, что они достаточно просты и говорят сами за себя, поэтому я просто покажу здесь исходный код. Сначала у нас есть MessageProducer, который помещает сообщение в очередь при его выполнении:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package net.pascalalma.aws.sqs;
 
import org.apache.log4j.Logger;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
 
@Service("myMessageProviderService")
public class MyMessageProvider {
 
    final static Logger logger = Logger.getLogger(MyMessageProvider.class);
 
    @Resource(name = "jmsTemplate")
    private JmsTemplate jmsTemplate;
 
    public void sendMessage(final String txt) {
        logger.debug(String.format("Sending message with txt: %s", txt));
        jmsTemplate.send(new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                final TextMessage msg = session.createTextMessage(txt);
                return msg;
            }
        });
        logger.debug("Message sent ");
    }
}

Далее следует MessageConsumer, который в этом примере просто читает одно сообщение из очереди, когда оно выполняется:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package net.pascalalma.aws.sqs;
 
import org.apache.log4j.Logger;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
 
import javax.annotation.Resource;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.TextMessage;
 
@Service("myMessageConsumerService")
public class MyMessageConsumer {
 
    final static Logger logger = Logger.getLogger(MyMessageConsumer.class);
 
    @Resource(name = "jmsTemplate")
    private JmsTemplate jmsTemplate;
 
    public void readMessage() throws JMSException {
        logger.debug("Reading message");
        Message msg = jmsTemplate.receive();
 
        if (msg instanceof TextMessage) {
            TextMessage txtmsg = (TextMessage) msg;
            logger.info(String.format("Received text: %s", txtmsg.getText()));
 
        }
        logger.debug(msg.getClass());
        logger.info("Done");
    }
}

Наконец, есть класс Main, который читает конфигурацию Spring и запускает Producer en Consumer:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package net.pascalalma.aws.sqs;
 
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
import javax.jms.JMSException;
 
public class SpringMain {
 
    final static Logger logger = Logger.getLogger(SpringMain.class);
 
    public static void main(String[] args) {
        //Build application context by reading spring-config.xml
        ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"application-context.xml"});
 
        //Get an instance of ProductService class;
        MyMessageProvider prdSvc = (MyMessageProvider) ctx.getBean("myMessageProviderService");
 
        MyMessageConsumer conSvc = (MyMessageConsumer) ctx.getBean("myMessageConsumerService");
 
        //Call getProduct method of ProductService
        prdSvc.sendMessage("This is a test");
 
        try {
            conSvc.readMessage();
        } catch (JMSException e) {
            logger.error(e);
        }
    }
}

При запуске класса Main вы увидите следующий вывод, когда все работает:

1
2
3
4
5
6
7
8
2015-03-29 10:26:39 DEBUG net.pascalalma.aws.sqs.MyMessageProvider(28) - Sending message with txt: This is a test
2015-03-29 10:26:41 DEBUG net.pascalalma.aws.sqs.MyMessageProvider(35) - Message sent
2015-03-29 10:26:41 DEBUG net.pascalalma.aws.sqs.MyMessageConsumer(24) - Reading message
2015-03-29 10:26:41 INFO  net.pascalalma.aws.sqs.MyMessageConsumer(29) - Received text: This is a test
2015-03-29 10:26:41 DEBUG net.pascalalma.aws.sqs.MyMessageConsumer(32) - class com.amazon.sqs.javamessaging.message.SQSTextMessage
2015-03-29 10:26:41 INFO  net.pascalalma.aws.sqs.MyMessageConsumer(33) - Done
 
Process finished with exit code 0