Spring Remoting с JMS и ActiveMQ

Spring Remoting с JMS и ActiveMQ

1. обзор

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

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

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

Apache ActiveMQ - этоopen source message broker, который позволяет приложениям обмениваться информацией асинхронно, и он полностью совместим сJava Message ServiceAPI.

Чтобы запустить наш эксперимент, нам сначала нужно настроить работающий экземплярActiveMQ. Мы можем выбрать один из нескольких способов: выполнить шаги, описанные вofficial guide, встроить его в приложение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,as explained here:


    org.springframework.boot
    spring-boot-starter-activemq
    
        
            org.springframework.boot
            spring-boot-starter-tomcat
        
    

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

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

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

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

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

The first step is to declare a bean that implements the interface of the service we want to expose to the clients. Это bean-компонент, который будет выполнять бизнес-логику на сервере:

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

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

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

Как мы уже знаем из предыдущих статей,one of the main concepts of Spring Remoting is the Service Exporter, the component that collects the invocation requests from some source, в данном случае очередьApacheMQ ─ и вызывает требуемый метод в реализации службы.

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

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

Наконец, нам нужно определить слушателя, который отвечает за потребление сообщений. listener acts as a bridge between ApacheMQ and the*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.example.api

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

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

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

Пакетcom.example.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 продолжает демонстрировать, как легко настроить асинхронный вызов независимо от основного канала.

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