2009-04-25 14 views
2

Ich bin immer noch mit Frühlings-Integration- kämpfen hier ist mein Szenario:Frühling Integration: Anspannen Web-Services zu einer FIFO-Warteschlange

  1. Ein Web-Service eine Anfrage von Client erhält A
  2. Webservice die Anforderung setzt auf eine Warteschlange
  3. eine Warteschlange Verbraucher verarbeitet die Nachrichten-FIFO und sendet eine Antwort, die Dienste wieder an den Webservice
  4. Webantwort A zu Client weitergeleitet wird
  5. sendet

Es gibt mehrere Webdienste, die alle Nachrichten in diese Warteschlange einspeisen, und ich muss sicherstellen, dass sie wirklich in der Reihenfolge verarbeitet werden, in der sie empfangen werden.

Welche Teile der Federintegration muss ich zusammen verdrahten?

+0

Wenn Sie sagen FIFO-Warteschlange meinen Sie eine QueueChannel (http://static.springframework.org/spring-integration/apidocs/org/springframework/integration/channel/QueueChannel.html), eine JMS-Warteschlange, oder etwas anderes? –

+0

Ein Queue-Kanal, ja –

Antwort

7

ich helfen würde aussehen gehen würde, kann nicht Sie mit Spring Integration, aber vielleicht müssen Sie Ihre Architektur einen zweiten Gedanken geben. In ESB-Systemen platzieren Sie normalerweise eine Nachricht in einer Warteschlange, wenn Sie wissen, dass die Verarbeitung der Nachricht sehr lange dauert oder wenn Sie nicht sicher sind, dass das Remote-Ende bereit ist (ein weiterer Grund besteht darin, inkompatible Komponenten zu überbrücken). Wenn Sie die Nachricht zur Warteschlange hinzufügen, kehren Sie sofort zum Anforderer zurück und geben an, dass die Nachricht empfangen wurde, jedoch nicht das Ergebnis der Operation. Der Anforderer würde dann nach dem Ergebnis fragen müssen, oder Sie könnten alternativ irgendeine Art von "Push" -Funktionalität bereitstellen.

Also, wenn die Verarbeitung der Nachrichten in der Warteschlange eine Menge Zeit braucht, empfehle ich, Ihre Architektur zu ändern. Es ist nicht üblich, dass ein Webclient lange auf die Antwort wartet, und viele Anfragen können ebenfalls eine Zeitüberschreitung verursachen.

Wenn die Verarbeitung der Nachrichten andererseits schnell und zuverlässig erfolgt, ist die Verwendung von Warteschlangenkanälen nicht erforderlich. Lassen Sie alle Ihre Nachrichten mit einer zentralen Komponente (Java EE Session Bean, Spring Bean, Webservice) kommunizieren und implementieren Sie selbst einen Warteschlangenmechanismus. Sie sind bereits Antworten darauf, wie Sie dies tun können.

1

Beachten Sie die Spring Integration, aber Java 5 verfügt über eine Reihe von BlockingQueues, die mit FIFO umgehen können.

+0

Danke, aber ich bin auf der Suche nach einer Spring Integration-Antwort, und vor allem eine Lösung für das Problem der Anbindung eines Web-Service an eine Warteschlange –

0

Das Problem ist nicht Frühling. Ich denke, dass Sie eine Warteschlange mit Elementen benötigen, die die Anfrage enthalten und eine Antwort anbieten. Aber die Antwort muss blockieren, bis das Element dequed und verarbeitet wird. So sieht das Warteschlangenelement wie folgt aus:

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; 
    } 
} 

Der Webservice Enqueining erstellt die BlockingPair mit seinem Anfragekörper. Schiebt dann das BlockingPair-Element in die Warteschlange. Danach erstellt er die Antwort, indem er den Antworttext von der BlockingPair holt, aber blockiert.

Der Verbraucher entwirft einen BlockingPair und stellt den Antwortkörper ein. Von dort schreibt der Webservice die Antwort weiter.

Sie benötigen drei Beans: Webservice, eine blockierende Warteschlange und den Verbraucher. Sowohl der Webservice als auch der Verbraucher benötigen die Warteschlange als Bean-Eigenschaft.

Die Warteschlange und die Consumer-Beans müssen im Anwendungskontext geplant werden (wie von der ContextLoaderListener initialisiert). Die Warteschlange braucht eine bean ID Referenzen durch den Webservice zu sein (das seinen eigenen Kontext hat, aber der Anwendungskontext als Eltern so kann die Warteschlange Bezug verwiesen werden):

Teil der 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> 
Die

applicationContext.xml enthält zwei Bohnen:

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

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

Der Webservice hat seine eigene Kontextdefinition, hier service-servlet.xml:

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

Weitere Informationen zum Definieren eines Endpunkts der Feder ws finden Sie unter spring tutorial.

Der Verbraucher muss eine Hintergrundaufgabe sein, also würde ich quartz bevorzugen, für die Federintegration siehe here.

+0

Wie ich in der Frage sage, ich suche eine Frühlingsintegrationslösung. Die Frühlingsintegration hat Warteschlangen und andere Klassen, aber ich bin mir nicht sicher, wie ich sie verbinden soll. –

2

Basierend auf der Javadoc für die QueueChannel hier ist mein Versuch es. Dies betrifft nicht die Web-Service-Konfiguration, sondern nur den Code, der in die Back-End-Implementierung des Web-Service eingehen würde.

Dies ist der Code, der einer Warteschlange (Ihrem Webdienst) etwas hinzufügen würde.

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); 
    } 
} 

Dies ist der Code, der in Ihrem Receiver/Prozessor/dequeue Klasse

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. 
    } 

} 

Die Spring-Konfiguration für diese so etwas wie

<?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

Sie sollten entweder die http (für REST) ​​oder die ws (für POX/SOAP) "Inbound-Gateway" -Elemente in der Spring-Integration betrachten. Entweder kann einer über den "request-channel" -Attribut mit einem geteilten queue-backed-Kanal verbunden werden (das Routing einer Antwort über dasselbe Gateway kann hinter den Kulissen abgewickelt werden). Ich würde empfehlen, mit dem Durchsuchen der Beispiele zu beginnen. Dieser Blog sollte Ihnen helfen, den Dienst zu starten: http://blog.springsource.com/2010/09/29/new-spring-integration-samples/

Hoffe, dass hilft. -Mark

+0

Zusätzlich zu dem, was Mark gesagt hat, wird das Anhängen dieses eingehenden Adapters an ein jms: Outbound-Gateway die Anforderung-Antwort-Anforderung erfüllen. – Pavel