Tech Ads
Back to Article List
Originally published November 2005 [ Publisher Link ]
BPEL: Web Services orchestration, hands-on with ActiveBPEL
Designing Web services in the context of an SOA entails striking a balance between a series of issues -- mainly reusability and flexibility -- but once this initial design is done coordinating individual services to play out their role in an aggregated manner implies another set of requirements, most of which can be addressed through BPEL, Business Process Execution Language.
BPEL was created as a joint effort by IBM, Microsoft and BEA in 2003, but since its inception, BPEL has gained traction among Web services standards. Currently under the auspices of OASIS and in its 2.0 version, more than thirty five companies are shaping the future direction this standard will take in addressing Web services orchestration.
But what does Web services orchestration through BPEL, or as some other companies term it Web services workflow or choreography, mean for someone already using the basic Web services stack SOAP/WSDL/UDDI? Lets tackle the issue, assuming you are assigned the task of migrating a credit application system and enabling it with Web services.
By its very nature, our credit application will surely be interacting with third party systems and in this same process have tens or hundreds of call variations based on these same Web services that need to be fulfilled in order to satisfy the requirements made by different system users.
Structuring these Web services decision chains or workflows is what BPEL has been designed for. However, before we delve further into its concrete use, you should be aware of one important aspect, perhaps even prerequisite, to realizing the value proposition behind BPEL: Reusability.
In order to structure as many Web services-based business processes and glue them together with BPEL a very fine balance needs to be achieved on each individual service. Having coarse-grained Web services may defeat the whole purpose of using BPEL for creating different decision chains since they may be complete business processes unto themselves. Similarly, fine-grained services may prove unwieldy to reuse and structure with BPEL workflows.
This process is similar in nature to that of object-orientated design, where an object needs to do enough work to justify its existence while holding off from trying to be an Über-object. You should think of Web service design in the same fashion. As a matter of course, Web service reusability is one of SOA's primary tenets, but the case proves more evident when using BPEL as we will see shortly.
At its core, BPEL provides the necessary XML grammar to express Web service interactions and as such has provisions for declaring variables, flow control, transactions and error handling among other things you would expect from a language charged with orchestrating cooperation.
Since this also implies a paradigm shift from the basic SOAP/WSDL/UDDI approach to Web services, BPEL requires its own environment in which to execute these instructions, properly named BPEL engine.
Currently, BPEL engines vary in maturity and deployment complexity. While some vendors in the SOA landscape are tightly integrating their BPEL engines with other core offerings such as ESB's - a term loaded with controversy to say the least - others are creating standalone products in this same space.
In order to obtain a firm grasp on BPEL we will take the latter approach and exemplify BPEL through the most neutral and non-invasive approach possible, a Java open source BPEL engine named: ActiveBPEL.
ActiveBPEL, being a standalone BPEL engine, is designed to operate under any Java/J2EE application server in the form of a Web application (WAR file). Given ActiveBPEL's roots in open source, it has strong ties to the de facto Java/J2EE open source container Tomcat , Apache's Web services framework Axis and the popular build tool Ant .
These characteristics make ActiveBPEL an excellent alternative for exploring BPEL's functionalities since its operation depends on well known and readily available technologies. In case you don't have these packages on your workstation, download them and follow the basic installation instructions. We wont stray into fancy configurations, since the whole point of this choice is to get you up to speed on BPEL as quickly as possible.
Let's take a high-level view at the orchestration process we will be trying to achieve through ActiveBPEL. Your banking system needs to execute a credit application process that returns either a simple "yes" or a "no" based on a series of elaborate chained decisions that are taken from such things as the amount of a loan, a solicitor's credit history or a branch location, all of which are fulfilled by calling individual Web services.
Due to market conditions or bank policies this business process will more than likely change the manner in which it qualifies or disqualifies a credit application. Having an Über Web service that returns the results would be an extremely inflexible approach since it would imply continuous modification to the business logic behind the Web service each time a modification is required. On the other hand, having a BPEL process orchestrate the application logic gives us two main benefits.
BPEL's XML grammar grants us a level of indirection in which to alter the application's workflow without the need to modify behind the scenes business logic while also leaving us the door open for later reuse of a set of core Web services in more complex workflow scenarios.
Let's assume we have arrived at a final design -- the difficult part -- for our core Web services. Our two Web services will be composed of an approver and an assessor. The initial analysis shows that both can easily be reused for other credit evaluation processes. So now it's time to look at BPEL pseudo-code and see what we need to create in BPEL-XML syntax.
if (creditapplication < $10,000) { if (assessor returns "lowrisk") return "yes" else return approver response else return approver response |
Our first step is checking the credit application amount. If this quantity is above a $10,000 threshold we hand of the input data to the approver Web service in order to obtain a response. On the other hand, if the application amount is below $10,000 we first invoke the assessor Web service, at which point, after returning an answer, if the response is "lowrisk" the application is immediately approved. Otherwise we need to make a further call to the approver Web service.
This is a very straightforward business process for our application, but one that clearly illustrates the power BPEL can achieve orchestrating different calling scenarios to our core Web services. Now lets take a look at the actual BPEL-XML syntax.
<?xml version="1.0" encoding="UTF-8"?> <process name="loanApprovalProcess" suppressJoinFailure="yes" targetNamespace="http://acme.com/loanprocessing" xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/" xmlns:apns="http://tempuri.org/services/loanapprover" xmlns:asns="http://tempuri.org/services/loanassessor" xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/" xmlns:lns="http://loans.org/wsdl/loan-approval" xmlns:loandef="http://tempuri.org/services/loandefinitions" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <partnerLinks> <partnerLink myRole="approver" name="customer" partnerLinkType="lns:loanApprovalLinkType"/> <partnerLink name="approver" partnerLinkType="lns:loanApprovalLinkType" partnerRole="approver"/> <partnerLink name="assessor" partnerLinkType="lns:riskAssessmentLinkType" partnerRole="assessor"/> </partnerLinks> <variables> <variable messageType="loandef:creditInformationMessage" name="request"/> <variable messageType="asns:riskAssessmentMessage" name="riskAssessment"/> <variable messageType="apns:approvalMessage" name="approvalInfo"/> <variable messageType="loandef:loanRequestErrorMessage" name="error"/> </variables> <faultHandlers> <catch faultName="apns:loanProcessFault" faultVariable="error"> <reply faultName="apns:loanProcessFault" operation="approve" partnerLink="customer" portType="apns:loanApprovalPT" variable="error"/> </catch> </faultHandlers> <flow> <links> <link name="receive-to-approval"/> <link name="receive-to-assess"/> <link name="approval-to-reply"/> <link name="assess-to-setMessage"/> <link name="assess-to-approval"/> <link name="setMessage-to-reply"/> </links> <receive createInstance="yes" name="receive1" operation="approve" partnerLink="customer" portType="apns:loanApprovalPT" variable="request"> <source linkName="receive-to-approval" transitionCondition="bpws:getVariableData('request', 'amount')>=10000"/> <source linkName="receive-to-assess" transitionCondition="bpws:getVariableData('request', 'amount')<10000"/> </receive> <invoke inputVariable="request" name="invokeapprover" operation="approve"outputVariable="approvalInfo" partnerLink="approver" portType="apns:loanApprovalPT"> <target linkName="receive-to-approval"/> <target linkName="assess-to-approval"/> <source linkName="approval-to-reply"/> </invoke> <invoke inputVariable="request" name="invokeAssessor" operation="check" outputVariable="riskAssessment" partnerLink="assessor" portType="asns:riskAssessmentPT"> <target linkName="receive-to-assess"/> <source linkName="assess-to-setMessage" transitionCondition="bpws:getVariableData('riskAssessment', 'risk')='low'"/> <source linkName="assess-to-approval" transitionCondition="bpws:getVariableData('riskAssessment', 'risk')!='low'"/> </invoke> <reply name="reply" operation="approve" partnerLink="customer" portType="apns:loanApprovalPT" variable="approvalInfo"> <target linkName="approval-to-reply"/> <target linkName="setMessage-to-reply"/> </reply> <assign name="assign"> <target linkName="assess-to-setMessage"/> <source linkName="setMessage-to-reply"/> <copy> <from expression="'approved'"/> <to part="accept" variable="approvalInfo"/> </copy> </assign> </flow> </process> |
Notice the various BPEL elements : <partnerLink>, <variable>, <faultHandler>, <flow>, >target>, among others. Obviously going into an exhaustive description of BPEL syntax would go beyond the scope of this article, but if you follow closely you will see the same patterns described in our pseudo-code. It should also be noted that most BPEL process are created using special editors in order to avoid the error prone process of writing XML by hand.
Having seen the actual BPEL process you might now be asking yourself were is the relation to our actual Web services -- the URI's, or WSDL descriptors? In the specific case of ActiveBPEL, this requires you define a Process Deployment Descriptor file which tells the BPEL engine about your processes. The following section shows this PDD file.
<process location="bpel/loanapproval.bpel" name="bpelns:loanApprovalProcess" xmlns="http://www.active-endpoints.com/schemas/deploy/pdd.xsd" xmlns:bpelns="http://acme.com/loanprocessing" xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing"> <!-- Partner Link for inbound request from customer --> <partnerLinks> <partnerLink name="customer"> <myRole allowedRoles="" binding="RPC" service="ApproveLoan"/> </partnerLink> <!-- Partner Link for outbound request to delegate approver --> <partnerLink name="approver"> <partnerRole endpointReference="static"> <wsa:EndpointReference xmlns:approver="http://tempuri.org/services/loanapprover"> <wsa:Address> approver:anyURI </wsa:Address> <wsa:ServiceName PortName="SOAPPort"> approver:LoanApprover </wsa:ServiceName> </wsa:EndpointReference> </partnerRole> </partnerLink> <!-- Partner Link for outbound request to risk assessment process --> <partnerLink name="assessor"> <partnerRole endpointReference="static"> <wsa:EndpointReference xmlns:assessor="http://tempuri.org/services/loanassessor"> <wsa:Address>assessor:anyURI</wsa:Address> <wsa:ServiceName PortName="SOAPPort"> assessor:LoanAssessor </wsa:ServiceName> </wsa:EndpointReference> </partnerRole> </partnerLink> </partnerLinks> <wsdlReferences> <wsdl location="project:/wsdl/loandefinitions.wsdl" namespace="http://tempuri.org/services/loandefinitions"/> <wsdl location="project:/wsdl/loanapproval.wsdl" namespace="http://loans.org/wsdl/loan-approval"/> <wsdl location="project:/wsdl/loanapprover.wsdl" namespace="http://tempuri.org/services/loanapprover"/> <wsdl location="project:/wsdl/loanassessor.wsdl" namespace="http://tempuri.org/services/loanassessor"/> </wsdlReferences> </process> |
Notice how this descriptor associates the location of the BPEL process we saw earlier in the declaration <process location="bpel/loanapproval.bpel"> defines physical addresses for each <partnerLink> and declares various WSDL descriptors.
In essence, this last file ties together the BPEL process with our actual Web services. With this last illustration, you should also realize that Web services WSDL files form the backbone of any BPEL process.
The previous statement holds true because WSDL contracts describe the methods, messages and characteristics of a Web service. And a BPEL process, through its engine, makes ample use of the information contained in these standard Web services documents in order to orchestrate the desired business process.
That concludes our look at BPEL through ActiveBPEL. Having looked at the Loan Approval Application for ActiveBPEL and addressed its inner workings, you should now be in a position to realize the value BPEL can bring to your Web services and SOA developments.