Spring Integration: подключение веб-сервисов к очереди FIFO - PullRequest
2 голосов
/ 25 апреля 2009

Я все еще борюсь с Spring Integration - вот мой сценарий:

  1. Веб-сервис получает запрос от клиента A
  2. веб-сервис помещает запрос в очередь
  3. Потребитель очереди обрабатывает сообщения FIFO и отправляет ответ, который направляется обратно в веб-службу
  4. Веб-сервисы отправляют ответ клиенту A

Будет несколько веб-сервисов, все сообщения которых поступают в эту очередь, и мне нужно убедиться, что они действительно обрабатываются в порядке их получения.

Какие части Spring Integration мне нужно соединить вместе?

Ответы [ 5 ]

7 голосов
/ 30 апреля 2009

Я не могу помочь вам с Spring Integration, но, возможно, вам нужно подумать о своей архитектуре. В системах ESB вы обычно помещаете сообщение в очередь, когда вы знаете, что обработка сообщения займет значительное время, или если вы не уверены, что удаленный конец готов (другая причина заключается в соединении несовместимых компонентов). Когда вы добавляете сообщение в очередь, вы немедленно возвращаетесь к запрашивающей стороне, указывая, что сообщение получено, но не предоставив результат операции. Затем запрашивающая сторона должна будет опросить результат, или вы можете в качестве альтернативы предоставить какую-то функцию «push».

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

Если, с другой стороны, обработка сообщений быстрая и надежная, то использование каналов очереди не требуется. Пусть все ваши сообщения будут взаимодействовать с центральным компонентом (Java EE Session Bean, Spring Bean, веб-сервис) и самостоятельно реализовать механизм очереди. Это уже ответы на вопросы, как вы могли бы сделать это.

2 голосов
/ 30 апреля 2009

На основе Javadoc для QueueChannel вот моя попытка сделать это. Это не относится к конфигурации веб-службы, а только к коду, который будет использоваться в реализации серверной части веб-службы.

Это код, который добавит что-то в очередь (ваш веб-сервис).

public class TheWebService {

  // Could also use QueueChannel, or PollableChannel here instead
  // just picked the most general one
  private org.springframework.integration.channel.MessageChannel queue;

  public void yourWebServiceMethod(SomeArg arg) {
     SomeObjectToPassThatExtendsMessage passed = someInitialProcessing(arg);
     queue.send(passed);
  }
}

Это код, который будет идти в вашем классе приемника / процессора / очереди

public class TheProcessor {

  // Could also use QueueChannel here instead
  // just picked the most general one
  private org.springframework.integration.channel.PollableChannel queue;

  // This method needs to be setup to be called by a separate thread.
  // See http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/scheduling/package-summary.html
  // and it's sub-packages.
  public void someProcessingPoller() {
     SomeObjectToPassThatExtendsMessage passed = queue.receive();
     // Do some processing with the passed object.
  }

}

Конфигурация Spring для этого будет выглядеть примерно так:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">

  <bean id="webService" class="mypackage.TheWebService">
      <property name="queue" ref="queue" />
  </bean>

  <bean id="processor" class="mypackage.TheProcessor ">
      <property name="queue" ref="queue" />
  </bean>

  <bean id="queue" class="org.springframework.integration.channel.QueueChannel"/>
</beans>
1 голос
/ 30 ноября 2010

В Spring Integration вы должны обратить внимание на элементы "inbound-gateway" http (для REST) ​​или ws (для POX / SOAP). Любой из них может быть подключен к общему каналу с поддержкой очереди через атрибут «request-channel» (маршрутизация ответа через тот же шлюз может быть обработана за кулисами). Я бы порекомендовал начать с просмотра образцов. Этот блог должен помочь вам начать работу: http://blog.springsource.com/2010/09/29/new-spring-integration-samples/

Надеюсь, это поможет. -Марк

1 голос
/ 25 апреля 2009

Обратите внимание на Spring Integration, но в Java 5 есть ряд BlockingQueues, которые могут обрабатывать FIFO.

0 голосов
/ 28 апреля 2009

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

public class BlockingPair {
  private final RequestBodyType request;
  private ResponseBodyType response;

  public BlockingPair(RequestBodyType request) {
    this.request = request;
  }

  public RequestBodyType getRequest() {
    return request;
  }

  public ResponseBodyType getResponse() {
    while (response == null) {
      Thread.currentThread().sleep(10);
    }
    return response;
  }

  public void setResponse(ResponseBodyType response) {
    this.response = response;
  }
}

Служба веб-сервиса создает BlockingPair со своим телом запроса. Затем помещает элемент BlockingPair в очередь. После этого он создает ответ, получая тело ответа от BlockingPair, но блокирует.

Потребитель запрашивает одну BlockingPair и устанавливает тело ответа. Оттуда веб-служба продолжает писать ответ.

Вам нужны три компонента: веб-сервис, очередь блокировки и потребитель. И веб-сервис, и потребитель нуждаются в очереди как свойство bean-компонента.

Очередь и компоненты-потребители должны планироваться в контексте приложения (как инициализировано ContextLoaderListener). Очередь нуждается в идентификаторе bean-компонента для ссылки веб-сервисом (который имеет свой собственный контекст, но контекст приложения является родительским, поэтому на ссылку на ссылку можно ссылаться):

Часть web.xml:

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
  <servlet-name>service</servlet-name>
  <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>service</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

applicationContext.xml содержит два боба:

<bean id="queue" class="java.util.concurrent.LinkedBlockingQueue"/>

<bean id="consumer" class="...">
  <property name="queue" ref="queue"/>
</bean>

Веб-сервис имеет свое собственное определение контекста, здесь service-servlet.xml:

<bean id="endpoint" class="org.springframework.ws.server.endpoint....PayloadEndpoint">
  <property name="queue" ref="queue"/>
</bean>

Для получения дополнительной информации об определении конечной точки пружины см. Учебное пособие .

Потребитель должен быть в фоновом режиме, поэтому я бы предпочел кварц , для интеграции пружин см. здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...