|
2002 年 8 月 01 日
最近發(fā)布的 Web 服務(wù)的業(yè)務(wù)流程執(zhí)行語言(Business Process Execution Language for Web Services,BPEL4WS)規(guī)范,其定位是成為整合方面的 Web 服務(wù)標(biāo)準(zhǔn)。您可以創(chuàng)建能夠如完成執(zhí)行 Web 服務(wù)調(diào)用、操作數(shù)據(jù)、拋出故障或終止一個(gè)流程等工作的不同活動(dòng),然后將它們連接起來,從而創(chuàng)建出復(fù)雜的流程。這些活動(dòng)可以嵌套到結(jié)構(gòu)化活動(dòng)中,結(jié)構(gòu)化活動(dòng)定義了其中的活動(dòng)的運(yùn)行方式,比如是串行或是并行還是取決于某些條件。本系列文章的目的是讓讀者對(duì) BPEL4WS 語言的不同組成部分有所了解,并教讀者如何創(chuàng)建他們自己的完整的流程。本系列文章的第一部分將引領(lǐng)讀者創(chuàng)建第一個(gè)簡(jiǎn)單的流程。后續(xù)的部分將以不同方式擴(kuò)展這個(gè)示例,以便闡述并解釋 BPEL4WS 語言的關(guān)鍵部分,包括數(shù)據(jù)操作、相關(guān)性、故障處理、補(bǔ)償以及 BPEL4WS 中的各種結(jié)構(gòu)化活動(dòng)。
為了演示怎樣用 BPELWS 創(chuàng)建和聚集活動(dòng),我將描述一個(gè)處理貸款請(qǐng)求的簡(jiǎn)單示例。本文將闡述一個(gè)整合的主要方面,還將說明服務(wù)的 WSDL 描述與 BPEL4WS 流程定義有什么關(guān)系以及 BPEL4WS 流程定義如何使用它。在解釋交互作用的伙伴、保存消息的容器以及和外界交互作用的活動(dòng)的使用(即 <receive> 、 <reply> 和 <invoke> )的過程中,我創(chuàng)建了一個(gè)完整的流程。除了描述這個(gè)流程如何運(yùn)行外,我還將說明如何使用可從 alphaWorks 上得到的 BPWS4J 引擎來部署和運(yùn)行該流程。
在這個(gè)示例(請(qǐng)參見 圖 1)中,客戶發(fā)出一個(gè)貸款請(qǐng)求;請(qǐng)求得到處理,然后客戶弄清楚貸款是否得到了批準(zhǔn)。一開始,中間那個(gè)步驟將包括向啟用 Web 服務(wù)的金融機(jī)構(gòu)發(fā)送申請(qǐng)并將決定告訴客戶。從客戶的角度看,該流程將使用他的申請(qǐng),然后給他發(fā)送一個(gè)應(yīng)答。下圖使用 BPEL4WS 概覽文章中引入的云狀圖說明了貸款請(qǐng)求流程的外部視圖。隨著我繼續(xù)這個(gè)系列教程,我將通過向處理請(qǐng)求的步驟增加復(fù)雜度來介紹 BPEL4WS 語言的其它方面。
圖 1. 貸款批準(zhǔn)流程的外部視圖
建立流程:
上面的行為包括:獲得消息、然后調(diào)用金融機(jī)構(gòu)的 Web 服務(wù)以及最后應(yīng)答客戶。在 BPEL 中用 <receive> 、 <invoke> 和 <reply> 活動(dòng)定義了這三個(gè)操作。然而,該流程需要定義這些簡(jiǎn)單的活動(dòng)彼此之間的關(guān)系,以便知道如何以及何時(shí)運(yùn)行這些活動(dòng)。在 BPEL 中通過使用結(jié)構(gòu)化活動(dòng)來定義這些關(guān)系,這些結(jié)構(gòu)化活動(dòng)在如何運(yùn)行它們包含的活動(dòng)方面定義了一些限制。在這個(gè)示例中,您想讓這三個(gè)操作一個(gè)接一個(gè)地發(fā)生。在 BPEL 中可以通過使用 <sequence> 活動(dòng)獲得這樣的順序,<sequence> 活動(dòng)首先包含 <receive> 來消費(fèi)消息,然后跟著是一個(gè) <invoke> 來和金融機(jī)構(gòu)交談,最后以 <reply> 來向客戶發(fā)送應(yīng)答。因此,上面的云狀圖將包含以這個(gè)順序進(jìn)行的三個(gè)活動(dòng)的流程,并且可以調(diào)用金融機(jī)構(gòu),如 圖 2所示。
圖 2. 云狀圖中是什么?貸款批準(zhǔn)流程的內(nèi)部視圖。
您在開始充實(shí)這個(gè)流程之前,需要正式描述將涉及到的各方以及將被交換和操作的消息。
創(chuàng)建服務(wù)描述:使用 WSDL
BPEL 整合對(duì)所涉及的服務(wù)的 WSDL 描述依賴性很大,這是為了引用正在被交換的消息、正在被調(diào)用的操作以及這些操作所屬于的 portType。在這個(gè)示例中,您將需要金融機(jī)構(gòu)以及這個(gè)流程本身的描述。要考慮到金融界使用一組統(tǒng)一的消息來描述貸款信息,并且在 清單 1的貸款定義中定義了這些消息。
清單 1:貸款定義 WSDL(loandefinitions.wsdl)
<definitions targetNamespace="http:///services/loandefinitions"
xmlns:tns="http:///services/loandefinitions"
xmlns:xsd="http://www./2001/XMLSchema"
xmlns="http://schemas./wsdl/">
<message name="creditInformationMessage">
<part name="firstName" type="xsd:string"/>
<part name="name" type="xsd:string"/>
<part name="amount" type="xsd:integer"/>
</message>
<message name="loanRequestErrorMessage">
<part name="errorCode" type="xsd:integer"/>
</message>
</definitions>
|
假定您知道有一個(gè)提供貸款批準(zhǔn)服務(wù)的金融機(jī)構(gòu),其描述如下面 清單 2所示。該金融機(jī)構(gòu)只包含單個(gè)操作“approve”,它用這個(gè)操作確定一個(gè)貸款請(qǐng)求的狀態(tài)。該操作把有關(guān)客戶的信息作為輸入,然后輸出一條包含應(yīng)答的批準(zhǔn)消息。在上面的 loandefinitions WSDL 中定義了輸入消息的定義。
清單 2:貸款批準(zhǔn)者 WSDL(loanapprover.wsdl)
<definitions targetNamespace="http:///services/loanapprover"
xmlns:tns="http:///services/loanapprover"
xmlns:xsd="http://www./2001/XMLSchema"
xmlns:loandef="http:///services/loandefinitions"
xmlns="http://schemas./wsdl/">
<import namespace="http:///services/loandefinitions"
location="http://localhost:8080/bpws-samples/loanapproval/loandefinitions.wsdl"/>
<message name="approvalMessage">
<part name="accept" type="xsd:string"/>
</message>
<portType name="loanApprovalPT">
<operation name="approve">
<input message="loandef:creditInformationMessage"/>
<output message="tns:approvalMessage"/>
<fault name="loanProcessFault"
message="loandef:loanRequestErrorMessage"/>
</operation>
</portType>
<binding ...> ... </binding>
<service name="LoanApprover">....</service>
</definitions>
|
流程本身只是將輸入消息轉(zhuǎn)發(fā)到這個(gè)服務(wù)中,并將輸出消息從這個(gè)服務(wù)中轉(zhuǎn)發(fā)出去。因此,流程將通過引用上面的 portType 來向用戶提供同一個(gè)描述。還要做的一件事情是為所使用的服務(wù)定義 serviceLinkType 。 serviceLinkType 最多定義兩個(gè)角色,這兩個(gè)角色引用的是由 serviceLinkType 鏈接在一起的任意兩個(gè)服務(wù)提供和需要的 portType。對(duì)于這個(gè)示例來說,這個(gè) serviceLinkType 將被用于把客戶鏈接到流程,以及將流程鏈接到貸款批準(zhǔn)者。因?yàn)榱鞒瘫旧砗唾J款批者都提供“approver”portType,所以只需要一個(gè)角色,并且它們二者都不要求用戶支持另一個(gè) portType。您為流程創(chuàng)建下面的 清單 3 中的代碼:
清單 3:貸款批準(zhǔn) WSDL(loan-approval.wsdl)
<definitions
targetNamespace="http:///wsdl/loan-approval"
xmlns="http://schemas./wsdl/"
xmlns:slnk="http://schemas./ws/2002/06/service-link/"
xmlns:xsd="http://www./2001/XMLSchema"
xmlns:lns="http:///wsdl/loan-approval"
xmlns:apns="http:///services/loanapprover">
<import namespace="http:///services/loanapprover"
location="http://localhost:8080/bpws-samples/loanapproval/loanapprover.wsdl"/>
<import namespace="http:///services/loandefinitions"
location="http://localhost:8080/bpws-samples/loanapproval/loandefinitions.wsdl"/>
<slnk:serviceLinkType name="loanApprovalLinkType">
<slnk:role name="approver">
<portType name="apns:loanApprovalPT"/>
</slnk:role>
</slnk:serviceLinkType>
<service name="loanapprovalServiceBP"/>
</definitions>
|
創(chuàng)建流程
創(chuàng)建這個(gè)流程的所有要求現(xiàn)在都已滿足。您以 <process> 元素開始定義,包括將使流程能夠引用需要的 WSDL 信息的名稱空間(在這個(gè)名稱空間( http://..../loandefinitions)中定義了消息定義)、貸款批準(zhǔn)者的目標(biāo)名稱空間( http://.../loanapprover)以及流程自己的 WSDL 的目標(biāo)名稱空間( http://.../loan-approval)。流程現(xiàn)在可以用貸款批準(zhǔn)者服務(wù)作為一個(gè)組件。
<process name="loanApprovalProcess"
targetNamespace="http:///simpleloanprocessing"
xmlns="http://schemas./ws/2002/07/business-process/"
xmlns:lns="http:///wsdl/loan-approval"
xmlns:loandef="http:///services/loandefinitions"
xmlns:apns="http:///services/loanapprover">
|
下一步是聲明涉及的各方。定義了已命名的伙伴,每個(gè)伙伴都有一個(gè) WSDL serviceLinkType 表明其特征。對(duì)于這個(gè)示例來說,伙伴是客戶和金融機(jī)構(gòu)?;锇榈?myRole/partnerRole 屬性指定了給定的 serviceLinkType 的伙伴和流程將如何交互。 myRole 屬性引用的是流程在 serviceLinkType 中將要扮演的角色,而 partnerRole 指定了伙伴將要扮演的角色。在下面的伙伴定義中對(duì)此進(jìn)行了闡述。貸款批準(zhǔn)流程為客戶提供了 loanApprovalPT 功能,金融機(jī)構(gòu)接著又為流程提供了這個(gè)功能。在上面的 圖 1和 2中可以看到這個(gè)關(guān)系。
<partners>
<partner name="customer"
serviceLinkType="lns:loanApproveLinkType"
myRole="approver"/>
<partner name="approver"
serviceLinkType="lns:loanApprovalLinkType"
partnerRole="approver"/>
</partners>
|
定義了伙伴之后,您就基本上為開始添加組成整合的活動(dòng)做好了準(zhǔn)備。我們?cè)倩仡^看一下您想讓流程做什么。為了申請(qǐng)貸款,客戶向流程發(fā)送一條消息,流程詢問金融機(jī)構(gòu)是否將接受貸款申請(qǐng),然后用另一條消息(要么是接受申請(qǐng)的消息,要么是拒絕申請(qǐng)的消息)應(yīng)答客戶。在 BPEL 中您如何做到這一點(diǎn)呢?首先,您需要將傳入的消息放在 BPEL 活動(dòng)可以訪問到它的地方。在 BPEL 中,數(shù)據(jù)被寫入到數(shù)據(jù)容器中并且從數(shù)據(jù)容器進(jìn)行訪問,這些數(shù)據(jù)容器可以保存特定的 WSDL 消息類型的實(shí)例。
從客戶伙伴和 loanApprovalPT 的定義可以很明顯地看出,客戶將發(fā)送一條 creditInformationMessage 類型的消息,然后得到一條 approvalMessage 類型的應(yīng)答。因此,添加了下面的容器列表,這些容器在 圖 2中用藍(lán)色圓柱體表示:
<containers>
<container name="request" messageType="loandef:CreditInformationMessage"/>
<container name="approvalInfo" messageType="apns:approvalMessage"/>
</containers>
|
與進(jìn)程交互:接收、調(diào)用、應(yīng)答
流程可能僅包含一個(gè)活動(dòng),在這個(gè)例子中就是 <sequence> ?,F(xiàn)在,您可以將一個(gè) receive活動(dòng)添加到 sequence中,這個(gè) receive活動(dòng)可以接收客戶的消息并把它保存到適當(dāng)?shù)娜萜髦小?receive活動(dòng)的定義必須包括將向活動(dòng)發(fā)送它的消息的伙伴,以及伙伴將把它作為這條消息的目的地的流程的端口類型和操作。以這一信息為基礎(chǔ),一旦流程獲得一條消息,它就搜索一個(gè)具有匹配的 partner-portType-operation 三元組的 receive活動(dòng),然后把消息交給這個(gè) receive 活動(dòng)。為了避免混淆,BPEL4WS 規(guī)范規(guī)定在同一時(shí)間不能有多個(gè)帶有相同的 partner-portType-operation 三元組的接收活動(dòng)處于活動(dòng)狀態(tài)。隨后,活動(dòng)將把消息放在指定的容器中,然后結(jié)束。您開始 sequence活動(dòng),然后將 receive添加到其中:
<sequence>
<receive name="receive1" partner="customer"
portType="apns:loanApprovalPT"
operation="approve" container="request"
createInstance="yes">
</receive>
|
下一步是詢問啟用 Web 服務(wù)的金融機(jī)構(gòu)是否將接受貸款。這是用一個(gè)常規(guī)的 Web 服務(wù)調(diào)用來完成的,該調(diào)用是在流程中由 Invoke 活動(dòng)定義。Invoke 活動(dòng)在運(yùn)行時(shí)將使用其輸入容器(input container)中的消息來調(diào)用指定的 Web 服務(wù),并將得到的應(yīng)答放入到輸出容器(output container)中,然后結(jié)束。請(qǐng)注意:將在“approver”伙伴上進(jìn)行調(diào)用以執(zhí)行 approve 操作。
<invoke name="invokeapprover"
partner="approver"
portType="apns:loanApprovalPT"
operation="approve"
inputContainer="request"
outputContainer="approvalInfo">
</invoke>
|
為了使流程對(duì)客戶的請(qǐng)求作出應(yīng)答,流程使用一個(gè) Reply 活動(dòng)。一旦一個(gè)應(yīng)答活動(dòng)到達(dá),將用流程所擁有的 partner-portType-operation 三元組來找出要把應(yīng)答發(fā)送給誰。因此,為了應(yīng)答通過 Receive 活動(dòng)到達(dá)的消息,您將需要一個(gè)帶有相同的三元組的 Reply 活動(dòng)。在這個(gè)例子中,您想要告訴客戶金融機(jī)構(gòu)的決定是什么,所以在調(diào)用的輸出容器中將會(huì)發(fā)現(xiàn)要被發(fā)送的消息: approvalInfo 。完成應(yīng)答之后,流程結(jié)束。您關(guān)閉了 sequence 標(biāo)記和 process 標(biāo)記。
<reply name="reply" partner="customer" portType="apns:loanApprovalPT"
operation="approve" container="approvalInfo">
</reply>
</sequence>
</process>
|
全部組合在一起
流程被部署之后就一直在等待,直到有人啟動(dòng)它為止。如果您稍加注意,就能看到 receive包含了一個(gè)名為“createInstance”、被設(shè)置為真的屬性。這向我們展示了進(jìn)入流程的一個(gè)入口點(diǎn)。 圖 3闡述了貸款批準(zhǔn)流程將如何運(yùn)行。
圖 3. 運(yùn)行貸款批準(zhǔn)流程。
圖注:箭頭上的數(shù)字表示步驟發(fā)生的順序。黑色信封是包含貸款請(qǐng)求的消息。紅色信封是包含對(duì)該請(qǐng)求的應(yīng)答的消息。
客戶機(jī)向流程管理器發(fā)送了一條帶有適當(dāng)?shù)娜M的消息之后,就會(huì)有一個(gè)流程實(shí)例被創(chuàng)建并開始運(yùn)行。在給定的示例中,流程將啟動(dòng) sequence,這個(gè) sequence接著將啟動(dòng) receive。消息已經(jīng)到達(dá),所以它將被放入“request”容器中。然后將發(fā)生 invoke。在調(diào)用后得到的消息被放入到“approvalInfo”容器中后, reply將獲取這個(gè)消息并將其發(fā)送給客戶,此時(shí)流程的實(shí)例結(jié)束。同一個(gè)流程的多個(gè)實(shí)例可以同時(shí)運(yùn)行。當(dāng)我解釋更復(fù)雜的流程時(shí),您將看到如何使用相關(guān)性(correlation)將消息路由到同一個(gè)流程的正確實(shí)例上以及如何從同一個(gè)流程的正確實(shí)例把消息路由出去。
在 BPWS4J 中運(yùn)行流程
如果您想運(yùn)行您剛剛創(chuàng)建的流程,您將需要獲得可以從 alphaWorks 得到的 BPWS4J 引擎。(請(qǐng)參閱 參考資料)。請(qǐng)按照所提供的安裝指導(dǎo)進(jìn)行,不要忘記將 bpws4j-samples.war 文件放在適當(dāng)?shù)哪夸浵拢员隳膽?yīng)用程序服務(wù)器可以找到它。
您在這里擁有的流程是 BPWS4J 發(fā)行版自帶的貸款批準(zhǔn)樣本的一個(gè)簡(jiǎn)化版本(也是該規(guī)范中帶有的一個(gè))。您將使用那個(gè)樣本中提供的貸款批準(zhǔn)者服務(wù),以及貸款批準(zhǔn)者和流程本身的 WSDL(loanapproval.wsdl)。那些文件和我們的文件完全一樣,除了流程的 WSDL 包含一個(gè)額外的 serviceLinkType (用于那些文件的流程使用的一個(gè)額外伙伴)之外。
請(qǐng)?jiān)谝娴奈臋n中查閱有關(guān)運(yùn)行 BPWS4J 樣本的信息。要運(yùn)行貸款批準(zhǔn)樣本,您可以完全照搬指導(dǎo)的前三個(gè)步驟。在關(guān)于如何使用貸款批準(zhǔn)樣本的第四步和第五步,有一些地方需要特別的更改。您要把您剛才創(chuàng)建的文件提供給服務(wù),而不是將發(fā)行版所提供的 loan-approval.bpel 文件給它。
要?jiǎng)?chuàng)建您將要使用的 BPEL 文件,請(qǐng)把上面定義的流程(從 <process> 元素的開始到結(jié)束)剪切并粘貼到也是名為 loanapproval.bpel 的文件中,然后把它保存到其它目錄下,以免覆蓋樣本。現(xiàn)在,當(dāng)您按照第 4 步所述對(duì)服務(wù)進(jìn)行部署時(shí),請(qǐng)將文檔中指定的流程的 WSDL 文件和您剛創(chuàng)建的 BPEL 文件提供給該服務(wù)(請(qǐng)參閱 參考資料以查找源代碼文件)。
然后,部署 Web 頁面將僅向您請(qǐng)求貸款批準(zhǔn)者伙伴的 WSDL 文件。請(qǐng)將文檔中描述的文件提供給這個(gè)頁面。要想知道您是否意外地部署了引擎自帶的 BPEL 文件,您可以通過檢查它是否要求您提供另一個(gè)伙伴的名為貸款評(píng)估者(loan assessor)的 WSDL 來自己判斷一下。如果它這樣做了,那么您就把樣本中的 BPEL 文件給它,而不是把我們的文件給它,然后您需要重新開始。所以,對(duì)于第 5 步,除了最后一句關(guān)于部署“assessor(評(píng)估者)”伙伴的內(nèi)容的那句話之外,您可以完全按照文檔所述進(jìn)行?,F(xiàn)在您已經(jīng)為運(yùn)行流程做好了準(zhǔn)備。請(qǐng)遵循有關(guān)執(zhí)行 BPWS4J 貸款批準(zhǔn)樣本的步驟。當(dāng)您請(qǐng)求貸款的時(shí)候,您將得到一個(gè) yes或 no 的應(yīng)答??蛻魴C(jī)能夠處理您的 BPEL 文件是因?yàn)閮蓚€(gè)流程的入口點(diǎn)相同,且名稱也相同。
如果您想要了解更多幕后的情況,請(qǐng)轉(zhuǎn)到 webapps/bpws4j/WEB-INF/classes目錄下的 log4j.properties 文件,取消對(duì)第 24 行的注釋,第 24 行的內(nèi)容如下:
log4j.logger.bpws.runtime.flow.base=DEBUG
|
這將向您顯示您創(chuàng)建的每個(gè)活動(dòng)何時(shí)開始運(yùn)行。
DEBUG [base] Scope loanApprovalProcess is running
DEBUG [base] Sequence null is running
DEBUG [base] Receive receive1 is running
DEBUG [base] Invoke invokeapprover is running
DEBUG [base] Reply reply is running
|
下一次
在本文的下一部分,我將講述更多關(guān)于 BPEL4J 語言的內(nèi)容,并且通過向貸款批準(zhǔn)示例中添加更多活動(dòng)來闡述如何使用它們。為避免混淆,添加的部分將繼續(xù)使該樣本保持與規(guī)范和 BPWS4J 發(fā)行版中的樣本較為接近。同時(shí),您可能還想閱讀已經(jīng)發(fā)表的關(guān)于語言和運(yùn)行時(shí)的其它文章。
參考資料
關(guān)于作者
 |
|
|
 |
Rania Khalaf 是 IBM TJ Watson 研究中心的 Componet Systems 小組的一名軟件工程師。2001 年,她從 MIT 獲得學(xué)士學(xué)位和工程碩士學(xué)位后進(jìn)入 IBM。Rania 是 IBM BPEL4WS 引擎的創(chuàng)建者之一,您可以從 alphaWorks 上獲得 BPWS4J。您可以通過 rkhalaf@watson.ibm.com與作者聯(lián)系。
|
|