EIP Patterns using BPEL
Some Enterprise Services Bus products like Apache ServiceMix offer components that support the Enterprise Integration Patterns. But when you look at Open ESB there is no XPath Splitter or Content Based Router. But OpenESB features a BPEL Engine Component that can be used for the realization of EIP Patterns. This series of articles explains how EIP Patterns can be realized using a BPEL service engine.
Enterprise Integration Patterns
Gregor Hohpe and Bobby Woolf are describing patterns for Enterprise Integration in their famous book. A pattern is a structured description of a problem and its solution. The EIP patterns are building blocks for the successful and efficient realization of integration solutions.
We start this series of articles describing how an XPath Splitter can be realize using BPEL.
What is a Splitter?
A Splitter is an integration component that can split a single message containing multiple elements into several smaller messages. Think of an order for example. An order often contains several items. Have a look at listing 1.
<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>
The order consists of three items. Suppose a backend system is only capable of processing a single item at once or each item have to be processed differently. Then the order has to be splitted into several items before processing. We are fortunate because XML is used for the order message. To get a list of items we can apply the following XPath query:
The execution of this query returns a node list containing the three items. In listing 2 you can see the first node.
<item xmlns="http://predic8.com/order/"> <quantity>2</quantity> <price>799.00</price> <good>Notebook</good> <item>
An XPath Splitter component can be configured to do the split for us. But how can we split an order using BPEL? Let´s have a look at a composite application that can do the trick from a bird’s eye perspective. The File Adapter connected to the FileIn Service of the OrderProcess gets orders containing multiple items. At the right side, the process is connected to a second File Adaptor. This Adaptor gets the simple item messages from the BPEL process.
The responsibility of the BPEL process is to split the order messages that are read by the file connector.
Figure 2 shows the corresponding BPEL Process. After receiving an order a forEeach activity loops over the items and invokes the file connector. The process is asynchronous and doesn't return anything back to the calling file connector. Let´s see how the items are split.
The forEach activity should count from one to the number of items. The total number of items can be computed by the following XPath statement:
Next we need an XPath statement to access the items by index. The predicate in square brackets filters the list of the item nodes by comparing the position of each item with the counter variable i of the foreach loop.
$OrderIn.part1/ns0:lineitems/ns0:item[position() = $i]
Listing 3 is showing the complete BPEL source code of the forEach action. The forEach loops over all the items. The scope inside the forEach is responsible for passing the single items as message to the next component. The type of the local itemOut variable is a WSDL message Type pointing to a XML Schema element of type item. The assign copies an item from the order into the itemOut variable depending on the forEach counter variable i. Then an invoke action is calling the next component and passing as message the item in the itemOut variable. After the last loop the process can be terminated.
<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>
The items are send in a sequence to the next component by default. To speed things up, the forEach can be configured to execute multiple loops at the same time. To activate this feature set the parallel attribute to true:
<forEach parallel="true" ... >
Unfortunately not every BPEL engine supports this BPEL 2.0 feature.
This article has shown that a dedicated XPath Splitter component is not necessary if you have BPEL at your disposal. In the next article of this series we describe how a message filter can be implemented using BPEL.