EIP Patterns mit BPEL

Von: Stefan Maibücher
Datum: 15. Juni 2009

Einige Enterprise Services Bus Produkte, wie z.B. der Apache ServiceMix, unterstützen die Enterprise Integration Patterns durch mitgelieferte Komponenten. Wenn man allerdings mit OpenESB bzw. Glassfish ESB arbeitet gibt es weder einen XPath Splitter noch einen Content Based Router. Allerdings bietet OpenESB eine BPEL Engine Komponente an, mit welcher sich die Umsetzung der EIP Patterns verwirklichen lässt. Diese Artikelserie soll diese Umsetzung mittels der BPEL Service Engine zeigen.

Gregor Hohpe und Bobby Woolf beschreiben in ihrem Buch die EIP Muster. Ein Muster stellt eine strukturierte Beschreibung eines Problems und dessen Lösung dar. Die EIP Muster bilden Lösungsansätze für die erfolgreiche und effiziente Umsetzung von Integrationslösungen.

XPath Splitter

Wir starten die Serie mit der Beschreibung eines XPath Splitters in BPEL.

Was ist ein Splitter?

Ein Splitter ist eine Integrationskomponente, die eine einzelne Nachricht, welche mehrere Elemente enthält, in mehrere kleinere Nachrichten aufteilt. Nehmen wir als Beispiel eine Bestellung. Eine Bestellung enthält meistens mehrere Positionen.

<order xmlns='http://predic8.com/order/'>
  <lineitems>
    <item>
      <quantity>2</quantity>
      <price>799.00</price>
      <good>Notebook</good>
    </item>
    <item>
      <quantity>1</quantity>
      <price>695.00</price>
      <good>PC</good>
    </item>
    <item>
      <quantity>3</quantity>
      <price>349.00</price>
      <good>Monitor</good>
    </item>
  </lineitems>
</order>
			
Listing 1: Eine Bestellung enthält einzelne Positionen

ESB Schulung
Erfahren Sie wie man EIP Patterns mit JBoss ESB, ServiceMix oder OpenESB nutzt in unseren Kursen zur Integration mit ESBs.

Die Bestellung in Listing 1 besteht aus drei Positionen. Nehmen wir an, dass ein Backend System nur einzelne Positionen verarbeiten kann bzw. dass jede Position anders verarbeitet wird. Die Bestellung muss also vor der Verarbeitung in mehrere Positionen aufgeteilt werden. Praktischerweise wird XML als Message Format benutzt. Um eine einzelne Position zu erhalten genügt die folgende XPath Abfrage:


/order/lineitems/item


Die Ausführung der Query gibt eine Liste mit drei Artikeln item Elementen. In Listing 2 können Sie den ersten Knoten betrachten.

<item xmlns="http://predic8.com/order/">
  <quantity>2</quantity>
  <price>799.00</price>
  <good>Notebook</good>
<item>
Listing 2: Der erste Knoten als Standalone Document

Ein XPath Splitter kann konfiguriert werden, um die Aufteilung in einzelne Elemente vorzunehmen. Aber wie kann dieser nun in BPEL realisiert werden? Lassen Sie uns einen Blick auf die Composite Applikation werfen, um die Applikation aus der Vogelperpektive zu sehen. Der File Adapter, der mit dem FileIn Service des OrderProzess verbunden ist bekommt die Bestellungen. Auf der rechten Seite wird der Prozess mit dem zweiten File Adapter verbunden. Dieser erhält die einzelnen Artikel vom BPEL Prozess.

Netbeans Casa Editor mit File Adapter

Abbildung 1: Netbeans Casa Editor mit File Adapter

Die Aufgabe des BPEL Prozesses ist es, die Bestellnachricht, welche der File Connector liest, aufzusplitten.

Abb. 2 zeigt den korrespondierenden BPEL Prozess. Nach dem Eingang einer Bestellung läuft eine ForEach Schleife über die Artikel und ruft den zweiten File Connector auf. Der Prozess läuft asynchron und liefert nichts dem aufrufendem File Connector zurück. Sehen wir uns nun an, wie die Artikel aufgeteilt wurden.

Diagramm des XPath Splitter BPEL Prozesses

Abbildung 2: Diagramm des XPath Splitter BPEL Prozesses

Die forEach Aktivität soll von eins bis zur Anzahl der Positionen iterieren. Die gesamte Anzahl der Bestellungen wird mit folgendem XPath Ausdruck ermittelt und in der Variable total abgelegt:


count($OrderIn.part1/ns0:lineitems/ns0:item)


Als nächstes benötigen wir einen XPath Ausdruck, um die Artikel über ihren Index zu erhalten. Das Prädikat in den eckigen Klammern filtert die Liste der items, indem es deren Position mit der Schleifenvariable i der forEach Schleife abgleicht.


$OrderIn.part1/ns0:lineitems/ns0:item[position() = $i]


Listing 3 zeigt den BPEL Quellcode der forEach Schleife. Die ForEach Schleife läuft über alle Artikel. In der Schleife selber wird jeder einzelne Artikel als Nachricht zur nächsten Komponente weitergereicht. Die lokale itemOut Variable ist eine WSDL Message, welche auf ein XML Schema Typ item verweist. Das Assign kopiert einen Artikel aus der Bestellung in die itemOut Variable anhand der Schleifenvariable i. Die anschliessende Invoke Funktion ruft die nächste Komponente auf und übergibt ihr als Nachricht den Artikel in der itemOut Variable. Nach dem letzten Schleifendurchlauf terminiert der Prozess.

<forEach name="ForEachItem" parallel="no" counterName="i">
  <startCounterValue>1</startCounterValue>
  <finalCounterValue>count($OrderIn.part1/ns0:lineitems/ns0:item)</finalCounterValue>
  <scope name="Scope1">
    <variables>
      <variable name="itemOut" messageType="tns:WriteInputMessage"/>
    </variables>
    <sequence name="Sequence1">
      <assign name="SetItemOut">
        <copy>
          <from>$OrderIn.part1/ns0:lineitems/ns0:item[position() = $i]</from>
          <to variable="itemOut" part="part1"/>
        </copy>
      </assign>
      <invoke name="ItemOut" partnerLink="ItemOut" operation="write" 
      portType="tns:FileOutboundPortType" inputVariable="itemOut"/>
    </sequence>
  </scope>
</forEach>
Listing 3: ForEach Schleife BPEL Code

Die Artikel werden "by default" nacheinander zur nächsten Komponente verschickt. Um den Prozess zu beschleunigen kann man die forEach Schleife so konfigurieren, dass sie mehrere Durchläufe zur selben Zeit durchführt. Um dieses Feature zu aktivieren müssen Sie das parallel Attribut auf true setzen:


<forEach parallel="true" ... >


Leider unterstützt nicht jede BPEL Engine dieses BPEL 2.0 Feature.

Dieser Artikel hat gezeigt, dass eine spezialisierte XPath Splitter Komponente nicht notwendig ist, wenn man BPEL zur Verfügung hat. Im nächsten Artikel dieser Serie werden wir zeigen, wie ein Message Filter mit BPEL implementiert werden kann.