SOA: Implementing Service-Oriented Orchestrations

6 min read

The hello process service is a simplified example of a WS-BPEL process service. It doesn’t use partner services to get the job done, simply composing a hello message based on the data sent by the client. In contrast, a real-world WS-BPEL process may invoke a lot of partner services during its execution.

The following sections take you through creating the documents composing the bpr archive of a poInfo WS-BPEL process service that interacts with two partner services. The partner services used in this example are the following: poOrderDocService and poOrderStatusService.

The poInfo process service discussed here is invoked when a client sends a request message containing two parameters: pono and par. The first one specifies the pono of the order document on which you need to get information, while the second one specifies what kind of information should be returned, meaning two possible choices: the entire document or the status of the document.

Since you are going to deploy the poInfo process service to the ActiveBPEL engine, you first need to create the required folders in your file system for the project. For example, you may create the folder named poInfo and then create the META-INF, bpel, and wsdl folders within it.

Creating the WSDL Definition Describing the WS-BPEL Process

As usual, the first step in creating the service is to create the WSDL definition describing that service to its clients. Here is the poInfo.wsdl document that you should save in the wsdl folder created within the poInfo folder, which is the root folder for this project:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="poInfo"
targetNamespace=
"http://localhost:8081/active-bpel/services/poInfoService.wsdl"




>
<import namespace="http://localhost/WebServices/wsdl/poOrderDoc"
location="http://localhost/WebServices/wsdl/po_orderdoc.wsdl"/>
<import namespace="http://localhost/WebServices/wsdl/poOrderStatus"
location="http://localhost/WebServices/wsdl/po_orderstatus.wsdl"/>
<types>
<schema attributeFormDefault="qualified"
elementFormDefault="qualified"
targetNamespace=
"http://localhost:8081/active-bpel/services/poInfoService.wsdl"
>
<element name="poInfoRequest">
<complexType>
<sequence>
<element name="pono" type="xsd:string"/>
<element name="par" type="xsd:string"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<message name="poInfoResponseMessage">
<part name="payload" type="xsd:string"/>
</message>
<message name="poInfoRequestMessage">
<part name="payload" element="tns:poInfoRequest"/>
</message>
<portType name="poInfoPT">
<operation name="getInfo">
<input message="tns:poInfoRequestMessage"/>
<output message="tns:poInfoResponseMessage"/>
</operation>
</portType>
<plnk:partnerLinkType name="poInfoLT">
<plnk:role name="poInfoProviderRole">
<plnk:portType name="tns:poInfoPT"/>
</plnk:role>
</plnk:partnerLinkType>
<plnk:partnerLinkType name="poDocLT">
<plnk:role name="poDocProviderRole">
<plnk:portType name="ns2:poOrderDocServicePortType"/>
</plnk:role>
</plnk:partnerLinkType>
<plnk:partnerLinkType name="poStatusLT">
<plnk:role name="poStatusProviderRole">
<plnk:portType name="ns3:poOrderStatusServicePortType"/>
</plnk:role>
</plnk:partnerLinkType>
</definitions>

As you can see, the above WSDL definition imports two definitions describing the poOrderDocService and poOrderStatusService partner services.

Note the use of the poInfoRequest complex type when defining the input message. This structure makes it possible for the client to send two parameters, namely pono and par, within a single request message.

Another important thing to note here is the use of three partner links. The first one defines the interaction between the WS-BPEL process service and its client, while the other two define the relationships between the WS-BPEL service and the poOrderDocService and poOrderStatusService partner services respectively.

Creating the WSDL Catalog

The next step is to create the wsdlCatalog.xml WSDL catalog document in the META-INF directory of the project. In this example, the document contains only one entry that refers to the poInfo.wsdl document discussed in the preceding section.

<?xml version="1.0" encoding="UTF-8"?>
<wsdlCatalog>
<wsdlEntry location="wsdl/poInfo.wsdl"
classpath="wsdl/poInfo.wsdl" />
</wsdlCatalog>

Creating the WS-BPEL Business Definition Containing Conditional Logic

The WS-BPEL definition you create in this example is a bit complicated. This is because the poInfo.bpel definition shown below contains conditional logic.

<?xml version="1.0" encoding="UTF-8"?>
<process



name="poInfo.bpel"
suppressJoinFailure="yes"
targetNamespace="http://poInfo.bpel">
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="wsdl/poInfo.wsdl"
namespace=
"http://localhost:8081/active-bpel/services/poInfoService.wsdl"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="http://localhost/WebServices/wsdl/po_orderdoc.wsdl"
namespace="http://localhost/WebServices/wsdl/poOrderDoc"/>
<import importType="http://schemas.xmlsoap.org/wsdl/"
location="http://localhost/WebServices/wsdl/po_orderstatus.wsdl"
namespace=
"http://localhost/WebServices/wsdl/poOrderStatus"/>

<partnerLinks>
<partnerLink myRole="poInfoProviderRole" name="poInfoProvider"
partnerLinkType="ns1:poInfoLT"/>
<partnerLink name="poDocRequester" partnerLinkType="ns1:poDocLT"
partnerRole="poDocProviderRole"/>
<partnerLink name="poStatusRequester" partnerLinkType="ns1:
poStatusLT" partnerRole="poStatusProviderRole"/>
</partnerLinks>
<variables>
<variable messageType="ns1:poInfoRequestMessage" name="poInfoReq
uestMessage"/>
<variable messageType="ns1:poInfoResponseMessage" name="poInfoRe
sponseMessage"/>
<variable messageType="ns2:getOrderDocInput" name="poDocRequest
Message"/>
<variable messageType="ns2:getOrderDocOutput" name="poDocRespon
seMessage"/>
<variable messageType="ns3:getOrderStatusInput" name="poStatusRe
questMessage"/>
<variable messageType="ns3:getOrderStatusOutput" name="poStatusR
esponseMessage"/>
</variables>
<sequence>
<receive createInstance="yes"
operation="getInfo"
partnerLink="poInfoProvider"
portType="ns1:poInfoPT"
variable="poInfoRequestMessage"/>
<if>
<condition>($poInfoRequestMessage.payload/ns1:par =
'doc')</condition>
<sequence>
<assign>
<copy>
<from part="payload" variable="poInfoRequestMessage">
<query>ns1:pono</query>
</from>
<to part="pono" variable="poDocRequestMessage"/>
</copy>
</assign>
<invoke inputVariable="poDocRequestMessage"
outputVariable="poDocResponseMessage"
operation="getOrderDoc"
partnerLink="poDocRequester"
portType="ns2:poOrderDocServicePortType">
</invoke>
<assign>
<copy>
<from>$poDocResponseMessage.doc</from>
<to>$poInfoResponseMessage.payload</to>
</copy>
</assign>
</sequence>
<elseif>
<condition>($poInfoRequestMessage.payload/ns1:par =
'status')</condition>
<sequence>
<assign>
<copy>
<from part="payload" variable="poInfoRequestMessage">
<query>ns1:pono</query>
</from>
<to part="pono" variable="poStatusRequestMessage"/>
</copy>
</assign>
<invoke inputVariable="poStatusRequestMessage"
outputVariable="poStatusResponseMessage"
operation="getOrderStatus"
partnerLink="poStatusRequester"
portType="ns3:poOrderStatusServicePortType">
</invoke>
<assign>
<copy>
<from>$poStatusResponseMessage.status</from>
<to>$poInfoResponseMessage.payload</to>
</copy>
</assign>
</sequence>
</elseif>
<else>
<assign>
<copy>
<from>'Wrong input parameter. Should be either
doc or status!'</from>
<to>$poInfoResponseMessage.payload</to>
</copy>
</assign>
</else>
</if>
<reply operation="getInfo"
partnerLink="poInfoProvider"
portType="ns1:poInfoPT"
variable="poInfoResponseMessage"/>
</sequence>
</process>

The most interesting part of the above WS-BPEL process definition is the if/ elseif/else construct. Schematically it looks like the following:

<sequence>

activities

<if>
<condition>...</condition>
<sequence>

activities

</sequence>
<elseif>
<condition>...</condition>

<sequence>

activities

</sequence>
</elseif>
<else>
activity
</else>
</if>

activities

</sequence>

Note the use of the inner sequence constructs in the above structure. The fact is that WS-BPEL doesn’t allow you to use more than one activity within if or elseif or else blocks. That is why you have to enclose a set of activities within any of those blocks with sequence.

Packt

Share
Published by
Packt

Recent Posts

Top life hacks for prepping for your IT certification exam

I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…

3 years ago

Learn Transformers for Natural Language Processing with Denis Rothman

Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…

3 years ago

Learning Essential Linux Commands for Navigating the Shell Effectively

Once we learn how to deploy an Ubuntu server, how to manage users, and how…

3 years ago

Clean Coding in Python with Mariano Anaya

Key-takeaways:   Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…

3 years ago

Exploring Forms in Angular – types, benefits and differences   

While developing a web application, or setting dynamic pages and meta tags we need to deal with…

3 years ago

Gain Practical Expertise with the Latest Edition of Software Architecture with C# 9 and .NET 5

Software architecture is one of the most discussed topics in the software industry today, and…

3 years ago