By Doron Sherman | Article Rating: |
|
January 1, 2000 12:00 AM EST | Reads: |
15,129 |
BPEL4WS is now moving rapidly into becoming the de facto standard for Web service orchestration with most platform vendors following in IBM and Microsoft footsteps after the submission of the specification to OASIS. This increased momentum and visibility will drive a great need for educating developers on how to put BPEL to work.
This article illustrates a payment flow example coded using BPEL, highlighting some of the main constructs of the language and demonstrating how the flow can be monitored and managed once it is deployed. The example can be extended in various ways to include more advanced language constructs. Such extensions will be illustrated in subsequent articles.
Business Flow Example
The PayFlow business flow example illustrated in this article is comprised of a client initiating a request to a BPEL process and ending with the process calling back the client with the result of the payment request (receipt). The process includes use of <receive> and <invoke> activities for interacting with the outside world which includes the client (request) and a partner (payment processor service). XML Variables are used for holding messages exchanged between the process and the partners. To make this example interesting, the payment processor service is asynchronous and can take anywhere from several minutes to several days before the service calls back the process. Another interesting element demonstrated by this example is the handling of exceptions and managing of timeouts. These constructs are instrumental to enable a BPEL process to deliver reliable business flows.

The payment processor service, as implemented, will return a normal result if the amount is less than $500. Otherwise, it will return a "transfer refused" fault, which will be handled as an exception by the PayFlow BPEL process. PayFlow also handles an "insufficient funds" fault, which may be thrown by the service. In addition, the PayFlow process specifies a timeout period and terminates if the payment processor takes more than 2 days (the timeout limit) to return a digital receipt indicating a successful fund transfer.
Creating Service Descriptions with WSDL
PaymentProcessor WSDL file
The asynchronous payment processor service provides the following operations: initiate, getStatus and pollResult, grouped under the PaymentProcessorService portType.
<portType name="PaymentProcessorService">
<operation name="initiate">
<input message="tns:initiatePaymentProcessorServiceSoapRequest" />
<output message="tns:initiatePaymentProcessorServiceSoapResponse" />
</operation>
<operation name="getStatus">
<input message="tns:getPaymentProcessorServiceStatusSoapRequest" />
<output message="tns:getPaymentProcessorServiceStatusSoapResponse" />
</operation>
<operation name="pollResult">
<input message="tns:pollPaymentProcessorServiceResultSoapRequest" />
<output message="tns:pollPaymentProcessorServiceResultSoapResponse" />
</operation>
The payment processor service also provides the operations onResult, onInsufficientFundException and onTransferRefusedException, grouped under the PaymentProcessorServiceCallback portType. Note that these callback operations will actually be invoked on the client of the service - in this case the PayFlow process.
<portType name="PaymentProcessorServiceCallback">
<operation name="onResult">
<input message="tns:onPaymentProcessorServiceResultSoapRequest" />
<output message="tns:onPaymentProcessorServiceResultSoapResponse" />
</operation>
<operation name="onInsufficientFundException">
<input message="tns:onInsufficientFundExceptionPaymentProcessorServiceSoapRequest" />
<output message="tns:onInsufficientFundExceptionPaymentProcessorServiceSoapServiceResponse" />
</operation>
<operation name="onTransferRefusedException">
<input message="tns:onTransferRefusedExceptionPaymentProcessorServiceSoapRequest" />
<output message="tns:onTransferRefusedExceptionPaymentProcessorServiceSoapResponse" />
</operation>
</portType>
<plnk:partnerLinkType name="PaymentProcessorService">
<plnk:role name="PaymentProcessorServiceService">
<plnk:portType name="tns:PaymentProcessorService" />
</plnk:role>
<plnk:role name="PaymentProcessorServiceRequester">
<plnk:portType name="tns:PaymentProcessorServiceCallback" />
</plnk:role>
</plnk:partnerLinkType>
PayFlow WSDL File
The PayFlow BPEL process provides the following operations: initiate, pollResult and PayFlowCallback, grouped under the PayFlow portType.
<portType name="PayFlow">
<operation name="initiate">
<input message="tns:initiatePayFlowSoapRequest"/>
<output message="tns:initiatePayFlowSoapResponse"/>
</operation>
<operation name="pollResult">
<input message="tns:pollPayFlowResultSoapRequest"/>
<output message="tns:pollPayFlowResultSoapResponse"/>
</operation>
</portType>
<portType name="PayFlowCallback">
<operation name="onResult">
<input message="tns:onPayFlowResultSoapRequest"/>
<output message="tns:onPayFlowResultSoapResponse"/>
</operation>
</portType>
The PayFlow WSDL file defines BPEL partner links for the process. The links associate roles with portTypes for the PayFlow process and for callbacks on its client ("requester").
<plnk:partnerLinkType name="PayFlow">
<plnk:role name="PayFlowService">
<plnk:portType name="tns:PayFlow"/>
</plnk:role>
<plnk:role name="PayFlowRequester">
<plnk:portType name="tns:PayFlowCallback"/>
</plnk:role>
</plnk:partnerLinkType>
<complexType name="PaymentRequest">
<sequence>
<element name="fromName" type="string"/>
<element name="fromAccount" type="string"/>
<element name="toName" type="string"/>
<element name="toAccount" type="string"/>
<element name="amount" type="double"/>
</sequence>
</complexType>
<complexType name="DigitalReceipt">
<sequence>
<element name="status" type="string"/>
<element name="confirmationID" type="string"/>
<element name="paymentRequest" type="s1:PaymentRequest"/>
</sequence>
</complexType>
You can view the complete contents of the the PayFlow WSDL file, including the details of the input and output messages for the operations described above.
Creating the Process with BPEL
After defining the process WSDL and examining the partner WSDL, we can now turn to defining the process logic using BPEL. First, we need to define the namespaces, which will allow the process to refer to the message types defined within the WSDL files and qualify other names appropriately.
<process name="PayFlow"
targetNamespace="http://demo.cxdn.com"
suppressJoinFailure="yes"
xmlns:tns="http://demo.cxdn.com"
xmlns:tpp="http://payment.org"
xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
<partnerLinks>
<partnerLink name="client"
partnerLinkType="tns:PayFlow"
myRole="PayFlowService"
partnerRole="PayFlowRequester"/>
<partnerLink name="PaymentProcessorService"
partnerLinkType="tpp:PaymentProcessorService"
myRole="PaymentProcessorRequester"
partnerRole="PaymentProcessorServiceService"/>
</partnerLinks>
Based on the requirements of the PayFlow process, it receives an initiatePayFlowSoapRequest message as input, communicates with the payment processor asynchronously through request and response messages, needs to handle transfer-refused and a insufficient-funds faults, and finally provides a digital receipt at the conclusion of its execution.
<variables>
<variable name="input"
messageType="tns:initiatePayFlowSoapRequest"/>
<variable name="digitalReceipt"
messageType="tns:onPayFlowResultSoapRequest"/>
<variable name="request"
messageType="tpp:initiatePaymentProcessorServiceSoapRequest"/>
<variable name="response"
messageType="tpp:onPaymentProcessorServiceResultSoapRequest"/>
<variable name="transferRefusedFailure"
messageType="tpp:handleTransferRefusedExceptionSoapRequest"/>
<variable name="insufficientFundFailure"
messageType="tpp:handleInsufficientFundExceptionSoapRequest"/>
</variables>
<sequence>
<receive name="receiveInput" partnerLink="client" portType="tns:PayFlow"
operation="initiate" variable="input" createInstance="yes"/>
After receiving the client message, the process proceeds to start the main sequence for processing the payment flow. This <sequence> activity is enclosed within a <scope> that defines a catchall fault handler for terminating the process upon encountering a network error while interacting with an external service. The sequence starts by copying the client request from the input variable to the request variable used for sending it to the payment processor.
<scope variableAccessSerializable="no">
<faultHandlers>
<catchAll>
<terminate/>
</catchAll>
</faultHandlers>
<sequence>
<assign>
<copy>
<from variable="input" part="parameters"
query="//xmlRequest"/>
<to variable="request" part="parameters"
query="/initiatePaymentProcessorService/xmlRequest"/>
<invoke name="invokePaymentProcessorService" partnerLink="PaymentProcessorService"
portType="tpp:PaymentProcessorService" operation="initiate" inputVariable="request"/>
<onMessage partnerLink="PaymentProcessorService" portType="tpp:PaymentProcessorServiceCallback"
operation="onTransferRefusedException" variable="transferRefusedFailure">
<invoke name="replyOutput" partnerLink="client" portType="tns:PayFlowCallback"
operation="onResult" inputVariable="digitalReceipt"/>
Resources
<pick>
<onMessage partnerLink="PaymentProcessorService" portType="tpp:PaymentProcessorServiceCallback"
operation="onResult" variable="response">
<assign>
<copy>
<from variable="response" part="parameters" query="result"/>
<to variable="digitalReceipt" part="parameters" query="/onPayFlowResult/result"/>
</copy>
</assign>
<terminate/>
</onMessage>
<onMessage partnerLink="PaymentProcessorService" portType="tpp:PaymentProcessorServiceCallback"
operation="onInsufficientFundException" variable="insufficientFundFailure">
<terminate/>
</onMessage>
<onAlarm for="P2D">
<terminate/>
</onAlarm>
</pick>
</sequence>
</process>
Published January 1, 2000 Reads 15,129
Copyright © 2000 Ulitzer, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Doron Sherman
Doron Sherman is the CTO of Collaxa, Inc., a Web Service Orchestration Server vendor and a BEA Partner located in Redwood Shores, California. He has been involved with Java since its early days and pioneered application server technology while being a founder and chief scientist at NetDynamics.
- BPEL Unleashed
- Developing Web Services with WebSphere Studio
- Developing Web Services with WebSphere Studio
- Building DB2-Based Web Services Using WebSphere, Part 2
- BPEL: Make Your Services Flow
- Building DB2-Based Web Services Using WebSphere: Part 1
- Web Services Orchestration
- Welcome to Web Services
- Straight-Through Processing and Orchestration of Web Services
- Rise of the Standards-Based Integration Machines