Перейти к основному содержимому

Spring Remoting с JMS и ActiveMQ

· 5 мин. чтения

1. Обзор

В предыдущей статье мы видели, как можно использовать Spring Remoting для предоставления RPC поверх асинхронного канала в виде очереди AMQP . Однако мы можем получить тот же результат и с помощью JMS .

В этой статье мы фактически рассмотрим, как настроить удаленный вызов с использованием Spring Remoting JMS и Apache ActiveMQ в качестве промежуточного программного обеспечения для обмена сообщениями.

2. Запуск брокера Apache ActiveMQ

Apache ActiveMQ — это брокер сообщений с открытым исходным кодом , который позволяет приложениям обмениваться информацией асинхронно и полностью совместим с API службы сообщений Java . ``

Чтобы запустить наш эксперимент, нам сначала нужно настроить работающий экземпляр ActiveMQ . Мы можем выбрать один из нескольких способов: выполнить шаги, описанные в официальном руководстве , встроить его в приложение Java или, проще говоря, запустить контейнер Docker с помощью следующей команды:

docker run -p 61616:61616 -p 8161:8161 rmohr/activemq:5.14.3

Это запустит контейнер ActiveMQ , который предоставляет через порт 8081 простой административный веб-интерфейс, через который мы можем проверить доступные очереди, подключенных клиентов и другую административную информацию. Вместо этого клиентам JMS потребуется использовать порт 61616 для подключения к брокеру и обмена сообщениями.

3. Зависимости Maven

Как и в предыдущих статьях, посвященных Spring Remoting , мы собираемся настроить сервер и клиентское приложение Spring Boot , чтобы показать, как работает JMS Remoting .

Как обычно, мы тщательно выбираем стартовые зависимости Spring Boot , как описано здесь :

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>

Мы явно исключили spring-boot-starter-tomcat , чтобы не иметь файлов .jar , связанных с Tomcat , в пути к классам. ``

Это, в свою очередь, не позволит механизму автоконфигурации Spring Boot запускать встроенный веб-сервер при запуске приложения, поскольку он нам не нужен.

4. Серверное приложение

4.1. Разоблачить сервис

Мы настроим серверное приложение, предоставляющее службу CabBookingService , которую смогут вызывать клиенты.

Первый шаг — объявить bean-компонент, реализующий интерфейс службы, которую мы хотим предоставить клиентам. Это bean-компонент, который будет выполнять бизнес-логику на сервере:

@Bean 
CabBookingService bookingService() {
return new CabBookingServiceImpl();
}

Затем определим очередь, из которой сервер будет получать вызовы, указав ее имя в конструкторе:

@Bean 
Queue queue() {
return new ActiveMQQueue("remotingQueue");
}

Как мы уже знаем из предыдущих статей, одной из основных концепций Spring Remoting является Service Exporter , компонент, который собирает запросы на вызов из какого-то источника , в данном случае очереди ApacheMQ ─ и вызывает нужный метод на реализации сервиса .

Для работы с JMS мы определяем JmsInvokerServiceExporter :

@Bean 
JmsInvokerServiceExporter exporter(CabBookingService implementation) {
JmsInvokerServiceExporter exporter = new JmsInvokerServiceExporter();
exporter.setServiceInterface(CabBookingService.class);
exporter.setService(implementation);
return exporter;
}

Наконец, нам нужно определить слушателя, который отвечает за потребление сообщений. Прослушиватель действует как мост между ApacheMQ и JmsInvokerServiceExporter , он прослушивает сообщения вызова, доступные в очереди, перенаправляет вызов экспортеру службы и сериализует обратно результаты:

@Bean SimpleMessageListenerContainer listener(
ConnectionFactory factory,
JmsInvokerServiceExporter exporter) {

SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(factory);
container.setDestinationName("remotingQueue");
container.setConcurrentConsumers(1);
container.setMessageListener(exporter);
return container;
}

4.2. Конфигурация

Давайте не забудем настроить файл application.properties , чтобы позволить Spring Boot настраивать некоторые основные объекты, например ConnectionFactory , необходимые слушателю. Значения различных параметров в основном зависят от способа

Значения различных параметров в основном зависят от того, как был установлен ApacheMQ , и следующая конфигурация является разумной конфигурацией для нашего контейнера Docker , работающего на той же машине, на которой мы будем запускать эти примеры:

spring.activemq.broker-url=tcp://localhost:61616
spring.activemq.packages.trusted=org.springframework.remoting.support,java.lang,com.foreach.api

Параметр spring.activemq.broker-url является ссылкой на порт AMQ . Вместо этого требуется более глубокое объяснение параметра spring.activemq.packages.trusted . Начиная с версии 5.12.2 ActiveMQ по умолчанию отклоняет любое сообщение типа

Начиная с версии 5.12.2 ActiveMQ по умолчанию отклоняет любое сообщение типа ObjectMessage , используемое для обмена сериализованным объектом Java , поскольку в некоторых контекстах оно считается потенциальным вектором для атаки на систему безопасности.

В любом случае можно указать AMQ принимать сериализованные объекты в указанных пакетах. org.springframework.remoting.support — это пакет, содержащий основные сообщения, представляющие собой вызов удаленного метода и его результат. Посылка

Пакет com.foreach.api содержит параметры и результаты нашего сервиса. java.lang добавлен, потому что объект, который представляет результат заказа такси, ссылается на String , поэтому нам также нужно сериализовать его.

5. Клиентское приложение

5.1. Вызвать удаленную службу

Теперь займемся клиентом. Опять же, нам нужно определить очередь, в которую будут записываться сообщения вызова. Нам нужно перепроверить, что и клиент, и сервер используют одно и то же имя.

@Bean 
Queue queue() {
return new ActiveMQQueue("remotingQueue");
}

Затем нам нужно настроить экспортер:

@Bean 
FactoryBean invoker(ConnectionFactory factory, Queue queue) {
JmsInvokerProxyFactoryBean factoryBean = new JmsInvokerProxyFactoryBean();
factoryBean.setConnectionFactory(factory);
factoryBean.setServiceInterface(CabBookingService.class);
factoryBean.setQueue(queue);
return factoryBean;
}

Теперь мы можем использовать удаленную службу, как если бы она была объявлена как локальный компонент:

CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));

5.2. Запустите пример

Также для клиентского приложения мы должны правильно выбрать значения в файле .properties приложения. В обычной настройке они будут точно соответствовать тем, которые используются на стороне сервера.

Этого должно быть достаточно, чтобы продемонстрировать удаленный вызов через Apache AMQ . Итак, давайте сначала запустим ApacheMQ , затем серверное приложение и, наконец, клиентское приложение, которое будет вызывать удаленную службу.

6. Заключение

В этом кратком руководстве мы увидели, как можно использовать Spring Remoting для предоставления RPC поверх системы JMS в виде AMQ .

Spring Remoting продолжает демонстрировать, как легко и быстро настроить асинхронный вызов независимо от основного канала.

Как обычно, вы найдете исходники на GitHub .