?
在SOA的上下文中設計WebServices必須處理好一系列問題,包括可重用性和靈活性等。然而,一旦最初的設計是讓獨立的服務一起以集成的方式出現就會導致另一些需求的出現,其中大多數可以被業務過程執行語言(Business Process Execution Language ,BPEL)來處理。
BPEL是由IBM、Microsoft和BEA在2003年共同發明的。但從誕生尹始,BPEL就得到了Web services標準的引導。現在,在OASIS的資助下已經升到了2.0版本,有超過35家公司正在參與規劃未來標準的方向,它將成為處理Web services編排的標準。
但如何通過BPEL來進行Web services編排呢?一些其它公司把它稱為Web services工作流,意思是已經使用基礎的Web services協議棧SOAP/WSDL/UDDI。讓我們來談這個問題之前先假設你被派去遷移一個信用卡應用系統并使用到Web services。
由于自身的特性,我們的信用卡應用程序必須與第三方系統交互,并且在同樣的過程中有成百的調用。她們基于同樣的Web services,這樣可以滿足不同系統用戶的要求。
BPEL就是用來構建這些Web services決策鏈或工作流的。但是,在更深入探討它的具體使用之前,你應該認識到一個重要事情或者說必備條件,即BPEL背后的價值:可重用性。
為了盡可能多的構建基于Web services的業務過程并用BPEL把它們粘合到一起,必須使每個獨立的服務都達到精確的平衡。使用粗粒度的Web services比使用BPEL創建不同決策鏈的整體目標更重要,因為它們可能是完整的業務過程。同樣的,細粒度的服務不利于重用和構建BPEL工作流。
這個過程本質上與面向對象的設計很類似,即一個對象需要完成足夠的工作來證明它的存在才能不被認為是上層調用對象。你應該用同樣的方式考慮Web service。Web service 的可重用性是SOA的一個主要原則,這自不必說,而在使用BPEL的時候這一點體現的更加明顯。
作為核心,BPEL用XML語法來表達Web service交互,而像聲明變量、流控、事務和錯誤處理等其它事情你可以讓另一種語言來負責編排協作。
因為這樣也隱含著Web servcies基本的SOAP/WSDL/UDDI方法,因此BPEL要求其自身環境能夠執行這些命令,我們稱之為BPEL引擎。
現在,BPEL引擎存在著不同的成熟度和復雜性。當SOA領域的一些廠商用其它核心產品例如ESB來緊密集成他們的BPEL引擎時,其他人則在同樣的領域創建單獨的產品。
為了牢固掌握BPEL,我們通過最中立和不侵權的方法,即一個叫做ActiveBPEL的開源Java BPEL引擎來看看下面的BPEL示例。
ActiveBPEL是一個單獨的BPEL引擎,可以在任何Java/J2EE應用服務器下以Web應用(WAR文件)的形式運轉。由于ActiveBPEL屬于開源產品,所以它與事實上的Java/J2EE開源Tomcat、Apache's Web services框架Axis以及流行的構建工具Ant緊密的結合在一起。
這些特點使ActiveBPEL成為開發BPEL功能的優秀產品,因為它基于已經被熟知并已獲得應用的技術。如果你的機器上還沒有這些包,可以下載它們并按照基本安裝命令進行安裝。我們不會談論配置問題,因為本文的目的是讓你能更快的使用BPEL。
讓我們從高層審視ActiveBPEL編排的過程。你的銀行系統需要執行一個信用卡應用過程,并根據一系列詳細的決策鏈返回一個簡單的"yes" or a "no"。這些決策鏈需要拿到貸款數額、某個律師的信用歷史或支出地點,所有這一切都是通過調用單獨的Web services來完成的。
根據市場條件或銀行政策,這個業務過程將很可能改變信用卡應用的驗證方式。用上層Web services返回結果是相當不靈活的方法,因為它使得每次修改Web services之后都要繼續修改業務邏輯。另一方面,讓BPEL過程來編排應用邏輯會給我們帶來兩大好處。
BPEL的XML語法授予我們一種指令級別,通過它可以改變應用的工作流而不必在現場業務邏輯之后再修改。這為我們以后在更復雜的工作流情況下重用某套核心Web services提供了方便。
假設我們已經為我們的核心Web servcies完成了最后的設計。我們有兩個Web services,它們組成了一個approver和一個assessor。初始分析顯示這兩個服務都能很容易地被其他信用演進過程重用。因此,現在來看BPEL的偽代碼并看看為創建BPEL-XML語法我們需要做什么。
if (creditapplication < $10,000) {
??????? if (assessor returns "lowrisk")
??????????????? return "yes"
??????? else
??????????????? return approver response
}
else
??????? return approver response
首先是檢查信用卡應用的數額。如果它的量超過$10,000,我們就把輸入的數據轉交給approver Web service以獲得一個響應。反之,如果數量在$10,000以下,我們就先調用assessor Web service,讓它返回一個回答,如果響應是"lowrisk",那么應用程序立即被證實。否則我們就需要進一步調用approver Web service。
這是一個很直接的業務過程,很明顯的展示了BPEL的強大,達到了為我們的核心Web services編排不同調用場景的目的。現在,讓我們來看看實際的BPEL-XML語法。
<?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>
注意BPEL的元素有<partnerLink>, <variable>, <faultHandler>, <flow>, >target>等等。繼續講解BPEL語法的含義超出了本問的范圍,但如果你跟進的話你就能發現在偽代碼中有同樣的模式。還要注意到,很多BPEL過程是使用特殊的編輯器創建的,這樣可以避免手寫XML時的錯誤。
在看過實際的BPEL過程后,你大概會問這跟實際的Web servcies的UPI或WSDL描述符有什么關系。在ActiveBPEL中,它需要你定義一個過程部署描述符(Process Deployment Descriptor)文件來告訴BPEL引擎你的過程。下面就是這個PDD文件。
<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>
注意這個描述符是如何與剛才的BPEL過程協作的。它聲明了<process location="bpel/loanapproval.bpel">來為每個<partnerLink>定義物理地址,并聲明了多個WSDL描述符。
重要的是,這個文件與我們的Web services一起綁定到BPEL過程。通過上面的講解,你應該能意識到Web services WSDL文件組成了任何BPEL過程的主體。
前面的因為WSDL定義了一個Web service的方法、消息和特征。而一個BPEL過程則通過它的引擎使得豐富的使用信息被包含在這些標準Web services文件中,以此來編排需要的業務過程。
本文通過ActiveBPEL讓大家了解BPEL。如果你已經看過Loan Approval Application for ActiveBPEL 并知道它的內部工作方式,那么現在就能體會到BPEL對給你的Web services和SOA開發所帶來的價值。