業務流程管理(BPM)是應用整合中的重要組成部分,通過BPM,可以將業務邏輯靈活,方便的組織起來,形成流程,以實現客戶的業務需求。
BEA Weblogic Integration提供的BPM可以將自動化流程和人工參與的工作流有機的統一起來,形成一個完整的流程。BEA Weblogic Workshop作為Weblogic Platform的開發工具,提供了圖形化的BPM開發介面,可以將客戶的業務邏輯封裝成Control,為BPM的節點所使用,並且提供了對於Channel的發佈和訂閱的Control,大大豐富了BPM的呼叫機制,使BPM建立在面向訊息的架構之上。
Channel是Weblogic Integration中提供的,為Message Broker所使用的格式化文本,Channel可以定義為XML或者普通文本,通過Integration管理控制臺,可以定義通過多種手段產生Channel,包括JMS,FILE,EMAIL,TIMMER等,這樣就不再將訊息局限於傳統的JMS範圍,大大豐富了訊息的涵義,為面向訊息的架構定義了豐富的訊息來源。
Weblogic Integration提供了內置的Channel的發佈和訂閱的Control:Message Broker (MB) Publish和Message Broker (MB) Subscription,當Channel定義為XML格式時,可以通過Xquery,對訂閱的Channel進行過濾。
文本講述了Weblogic Integration中基於Message Broker實現BPM之間的呼叫,涉及的內容有如何定義Channel,如何通過Channel的發佈和訂閱機制實現BPM呼叫,如何過濾Channel,如何定義產生Channel等,並且通過一個事例,講述如何建製松耦合的BPM呼叫。
準備知識 XMLBean Weblogic Platform8.1提供了對於XML的強化支援,主要是通過XMLBean來實現的,當使用者通過Workshop,編寫了XML的Schema後保存時,Workshop會自動按照Schema,生成XMLBean的子類,通過生成的內置類和方法,可以實現XML的解析和XML元素的生成,修改和讀取。 舉例來說,下面是XML Schema的一個例子: <?xml version="1.0"?> <xs:schema targetNamespace="http://dev2dev.bea.com.cn/demo" xmlns="http://dev2dev.bea.com.cn/demo" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="ProcessCall"> <xs:complexType> <xs:sequence> <xs:element name="SendInfo"> <xs:complexType> <xs:sequence> <xs:element name="sender" type="xs:string"/> <xs:element name="identifyid" type="xs:string"/> <xs:element name="senddate" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="ReceiveInfo"> <xs:complexType> <xs:sequence> <xs:element name="receiver" type="xs:string"/> <xs:element name="identifyid" type="xs:string"/> <xs:element name="receivedate" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="xmlcontent" type="xs:string"/> <!--set xml context in this element --> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
在Process application下的Schemas目錄中新建一個XML Schema檔,將以上內容拷貝到該檔中,保存,則Workshop會自動生成相關的XMLBean的類檔,類的結構如下:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3018.png) 可以看到,所有類的結構與Schema檔的名字無關,類的package與Schema的命名空間(xmlns="http://dev2dev.bea.com.cn/demo")有關,而類的名字,內置類等與Schema內部定義的元素有關,由此我們可以知道,通過命名空間和根元素,在當前Application中,就能確定唯一的XMLBean類。
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3018.gif) 上圖說明瞭怎樣通過內置類和方法取得XML內部元素,值得注意的是Parse中的方法呼叫時,參數應該是整個XML字串,包括<?xml version="1.0" ?>,否則不能正確解析。而ProcessCallDocument提供的XmlText()的方法,輸出的XML字串卻不包含這些資訊,所以,當內部進行轉換時,需要人工加上,稍後我們的例子中會涉及這一點。
以上只是關於XMLBean的基本知識,是為了後面說明Channel使用,如果讀者希望瞭解詳細的XMLBean的知識,可以參照Workshop幫助檔案或者本站的其他檔案。
Channel格式定義 Channel格式定義檔也是在Process Application下的Schemas目錄中,讀者可以通過右鍵,選擇建立Channel檔,然後輸入test.channel作為檔案名稱,Workshop會自動建立test.channel的檔內容。
忽略檔中的注釋,可以看到,自動生成的Channel檔內容如下:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3016.gif) 我們希望能夠以前面提到的test.xsd中定義的XML來定義一種Channel的資料格式,由於test.xsd中定義的命名空間是xmlns="http://dev2dev.bea.com.cn/demo",所以我們需要修改Channels標籤中的命名空間首碼定義,加入該命名空間的首碼,同時修改Channel的首碼名稱。Channel檔中已經自動生成了關於XML格式的Channel的注釋,參照注釋,我們可以將Channel檔修改如下:
<?xml version="1.0"?> <channels xmlns="http://www.bea.com/wli/broker/channelfile" channelPrefix="/DemoChannel" xmlns:demo="http://dev2dev.bea.com.cn/demo" > <channel name ="CallProcessChl" messageType="xml" qualifiedMessageType="demo:ProcessCall"> </channel> </channels>
在該Channel檔中,我們定義了一種命名空間的首碼-demo(xmlns:demo="http://dev2dev.bea.com.cn/demo"),又在定義Channel的過程中,指出了格式是XML,它的命名空間首碼是demo,並且根元素是ProcessCall。
在Workshop的Application中,一旦確定了命名空間和根元素,則XML的Schema也是唯一確定的,這樣,就可以確定了該Channel的格式,我們也可以通過Control,發佈和訂閱該Channel,實現這種格式的訊息的傳遞。
稍後我們可以看到,發佈和訂閱Channel時,該Channel的名字是/DemoChannel/CallProcessChl,是Channel定義檔中的channels標籤裏的channelPrefix屬性和Channel標籤中的name屬性構成的,通過Channel的名字,可以在Weblogic Integration中定位Channel。
通過Channel呼叫BPM 如下圖,我們建立一個Process Application,名字為inwebbpm(注意:選擇server時選擇事先建立好的weblogic platform domain),我們在其中的inwebbpmWeb project上選擇安裝web project libraries,將以上的test.xsd和test.channel匯入到Schemas目錄中,則自動會生成的目錄結構如圖:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3015.png) 在processes目錄下我們建立兩個process:process.jpd和sub1.jpd。
在Process.jpd中,我們選擇開始節點類型為client request,選擇參數類型為String,參數名稱為substr,然後選擇將該參數的值儲存到內部變數substr中。
為了使用channel,我們需要建製ProcessCall格式的XML內容,在Process.jpd中增加Transformation Control,變數的名稱為pccalldt,然後選擇建立新的Transformation Control,檔名稱為PCCallDT。編輯PCCallDT.dtf,在其中增加方法buildPCCallXML,設定Xquery轉換方法時,如下圖指定參數:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3014.png) 在編輯buildPCCallXML.xq時,將輸入的的值賦給ProcessCall/xmlcontent。 將pccalldt的方法buildPCCallXML拖入process設計視圖中,生成節點,將內部substr作為輸入值,建立內部變數processcall1,類型為cn.com.bea.dev2Dev.demo.ProcessCallDocument,接受輸出值。
在Process.jpd中增加MB Publish Control,輸入的參數如下圖:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3013.png) 將mbpub的內部publish方法拖入process的設計視圖,生成節點,將內部變數processcall1作為輸入值。選擇查看原始碼,在mbpubPublish方法中的注釋前,加入調校資訊:
System.out.println("I am main process!");
編輯sub1.jpd,將開始節點的類型選擇為訂閱Message Broker,雙擊節點,選擇Channel的名字為/DemoChannel/CallProcessChl,建立內部變數processcall1,類型為cn.com.bea.dev2Dev.demo.ProcessCallDocument,接受輸出值。編輯接收節點的原始碼,在其中的注釋下面,加入如下原始碼: System.out.println("I am sub1 process!"); System.out.println(processcall1.xmlText());
啟動Weblogic Server,選擇process.jpd,運行,在測試介面中輸入sub1,提交,可以看到控制臺出現如下資訊: I am main process! I am sub1 process! <demo:ProcessCall xmlns:demo="http://dev2dev.bea.com.cn/demo"><demo:xmlcontent>sub1</demo:xmlcontent></demo:ProcessCall> 這表示通過Channel,實現BPM的呼叫已經初步成功。
訂閱時過濾Channel 設計ProcessCall的XML Schema時,我們就希望能將它作為BPM之間互相呼叫的通用的資料傳遞格式,其中的xmlcontent元素,發佈Channel時,我們可以將含有業務邏輯的XML整個字串賦給它,當訂閱了該Channel的BPM接收時,可以對xmlcontent值運行parse,解析出含有業務邏輯的XML,再處理業務邏輯。 但是Message Borker處理Channel的發佈和訂閱時,所有訂閱Channel的BPM都會接收到發佈的資訊,被啟動運行,有時候我們不希望這樣。設想我們現在又建立了一個sub2.jpd,與sub1.jpd類似,只是訂閱節點的調校資訊如下: System.out.println("I am sub2 process!"); System.out.println(processcall1.xmlText());
當我們重新運行process.jpd時,可以看到控制臺顯示的資訊如下: I am main process! I am sub1 process! <demo:ProcessCall xmlns:demo="http://dev2dev.bea.com.cn/demo"><demo:xmlcontent>sub1</demo:xmlcontent></demo:ProcessCall> I am sub2 process! <demo:ProcessCall xmlns:demo="http://dev2dev.bea.com.cn/demo"><demo:xmlcontent>sub1</demo:xmlcontent></demo:ProcessCall>
這說明process.jpd發佈了channel,所有訂閱該channel的bpm都會被啟動執行,在某些情況下,我們不希望這樣,而是希望能根據ProcessCall的內容進行有選擇的觸發。
這就需要通過Channel的過濾來實現。
編輯sub1.jpd的訂閱節點,按照下圖設定過濾資訊,意味著該BPM雖然訂閱了/DemoChannel/CallProcessChl,但是,只接收內部元素receiver的值為sub1的資訊。相類似的,我們將sub2.jpd修改為只接收內部元素receiver的值為sub2的資訊。
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3012.png) 分別通過Debug功能表下的start運行編譯兩個process後,通過http://localhost:7001/wliconsole/讀取Weblogic Integration的控制臺,進入Message Broker,點擊/DemoChannel/CallProcessChl的連結,可以看到該Channel的訂閱者資訊:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3011.png) 編輯PCCallDT.dtf下的buildPCCallXML.xq,將輸入的的值同時賦給/ProcessCall/ReceiveInfo/Receiver。
再運行process.jpd,可以看到,根據輸入的substr的值不同,控制臺會顯示不同的資訊,當輸入的值為sub1時,激發了sub1.jpd,當輸入的值為sub2時,激發了sub2.jpd,而當輸入值為其他時,沒有子BPM被啟動的資訊。
BPM內部動態訂閱和過濾Channel 上面的例子只是主BPM通過Channel呼叫子BPM,沒有返回資料給主BPM,而大多情況下,需要子BPM處理完畢後,將資料返回給主BPM,這時,我們就需要通過MB Subscription Control進行動態訂閱和過濾Channel,實現主BPM對於返回資料的接收。
通過MB Subscription Control,我們可以在BPM執行過程中訂閱Channel,BPM執行到MB Subscription Control的onMessage方法時會等待,一直到符合訂閱條件的Channel被發佈出來。在這裏,我們也需要過濾Channel的內容,但是與BPM的訂閱起始節點不同的是,我們過濾的不是某一類的Channel,而是與當前運行的BPM具有聯繫的Channel,這就要考慮過濾的內容應該是與當前運行的BPM相關的,是獨一無二的。
每個BPM在系統中運行時,都會被分配給一個唯一的ProcessID,通過ProcessID,我們就能實現資訊的接收訂閱,為了讓子BPM發回的Channel內容包含Processid,我們需要在呼叫BPM時,將主BPM的ProcessID作為Channel內容的一部分,傳遞給子BPM,子BPM返回資料前,再重新組裝資訊。
編輯Process.jpd,添加內部變數processid,類型為String,點擊 buildPCCallXML節點,選擇查看原始碼,在方法內部注釋後面加入如下原始碼:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3010.png) 這部分原始碼取得當前的processid,然後賦值給Channel的XML的內部元素。值得注意的是,由於呼叫的buildPCCallXML方法沒有給XML內部的複雜元素(含有子元素的內部元素)SendInfo賦值,所以該元素對應的內部類為null,呼叫時必須通過方法添加(例如.addNewSendInfo()),才可以對其內部的子元素進行賦值,否則會出現空指針異常。
在process.jpd中添加MB Subscription Control,設定的參數如下圖:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3009.png) 編輯生成的MBSub.jcx檔,修改如下:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3008.png) 上圖中紅色圖框內是添加的欄位,說明該Control對訊息的內容進行過濾,值得注意的是,需要聲明命名空間,而代表的是XML的根元素,所以過濾的就是/ProcessCall/ReceiveInfo/identifyid,而過濾的值就是subscribeWithFilterValue的方法的參數值。
過濾的設置也可以在MBSub.jcx的設計視圖中,找到Property Editor視窗下的xquery,點擊輸入框後邊的按鈕,在彈出的視窗中可以看到XML的格式,選擇/ProcessCall/ReceiveInfo/identifyid,然後點擊確定即可。
重新打開process.jpd,在設計視圖中,將mbsub的subscribeWithFilterValue方法拖入視圖,生成節點,雙擊節點進行編輯,在Send Data標籤中,選擇變數processid,作為輸入值。
將mbsub的onMessage方法拖入視圖,生成節點,雙擊節點進行編輯,在Receive Data標籤中,選擇變數processcall1,作為輸出結果值。右鍵選擇查看原始碼,在對應的方法中的注釋後面,加入如下原始碼:
編輯PCCallDT.dtf,添加Transformation方法returnPCCallXML,選擇設定Xquery方法,輸入和輸出的參數都選擇test.xsd下的ProcessCall,然後建立Transformation,如下圖進行轉換,將發送者的資訊寫入接受者標識中:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3006.png) 打開sub1.jpd,將PCCallDT.dtf拖入sub1的設計視圖中,自動生成變數pCCallDT,在Data Palette視窗內的Controls下會看到該變數,將該變數的returnPCCallXML方法拖入sub1的設計視圖中,生成節點,選擇輸入和輸出值都是processcall1。將MBPub.jcx拖入sub1的設計視圖中,系統會自動生成mbpub的變數,類型是MB Publish Control。拖mbpub下的publish方法到sub1的設計視圖中,在最後生成節點,編輯節點,將輸入值選擇為processcall1,編輯該節點對應的方法,在注釋前加入如下語句:
this.processcall1.getProcessCall().getReceiveInfo().setReceiver("main");
該語句的目的是修改/ProcessCall/ReceiveInfo/receiver的值,以避免發佈時,再被當前process訂閱接收,進入閉環。
按照以上步驟同樣修改sub2.jpd,但是跳過加入PCCallDT.dtf的returnPCCallXML方法為節點的一步,直接將訊息發佈回去。
分別運行Start,編譯sub1.jpd,sub2.jpd。兩次運行process.jpd,將substr的值分別輸入為sub1和sub2,可以看到控制臺輸出資訊如下,說明動態訂閱和過濾已經發生了效用。
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3005.png) 通過http://localhost:7001/wliconsole/讀取Weblogic Integration的管理控制臺,進入Process Instance Monitoring,可以看到右邊有系統process對應的事例統計情況,點擊display name為process的連結,可以看到有一個instance還在運行,該instance的ID應該就是上圖中sub2列印出的資訊的processid的值,點擊查看詳細資料,可以看到該instance等待在onMessage方法節點上。
再運行process.jpd,輸入sub1,然後重新查看Process的Instance,可以看到新完成了一個process的事例,但是上面提到的那個由於沒有收到相應的資訊,還是會處於運行狀態。
通過JMS產生Channel,建製松耦合的架構 Channel在整個Application中對於開發是可見的,而對於運行來說,對於整個Integration是可用的,即你可以通過在多個Application中定義相同的Channel,來實現多個Application之間BPM呼叫,這種靈活度大大超過了通過BPM Control實現BPM相互之間的呼叫。
那麼,不同的Weblogic Integration之間如何利用Channel呢?這就需要通過Event Generators來產生Channel,可以通過管理控制臺進行設定,將JMS,FILE,TIMER,EMAIL等產生的資訊作為Channel,為系統使用,這樣,就可以在多個Weblogic Integration中使用相同的XML Schema檔和Channel檔,然後通過JMS,FILE,TIMER,EMAIL等來實現資訊的傳遞。
使用這種方法,需要修改Channel的發佈,例如通過JMS,需要將Channel的發佈修改為發送JMS訊息,而訂閱Channel的部分,不再需要修改,可以繼續使用。
通過http://localhost:7001/console/連結到Weblogic Server的管理控制臺,建立一個新的JMS Server,在其下建立一個新的JMS Topic,JNDI的值為bpmTopic。
在process.jpd中添加JMS Control,設定如圖:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3003.png) 刪除publish節點,將mbjms的sendTextMessage方法拖到publish原來的位置,生成新的節點,雙擊編輯該節點,在Send Data中選擇建立新的變數為輸入值,變數名稱為xmlstr。右鍵查看原始碼,在對應的方法內注釋前面加入如下原始碼:
System.out.println("I am main process 2!"); this.xmlstr="<?xml version="1.0"?>"+this.processcall1.xmlText(); 正如我們前面提到的,這裏需要在前面加入XML的頭資訊。
通過http://localhost:7001/wliconsole/讀取Weblogic Integration的管理控制臺,進入Event Generators,通過左邊連結,切換到JMS,點擊Create New,設定的資訊如下:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3002.gif) 提交後,點擊右邊下方的Define a New Channel Rule連結,不要修改任何參數,直接提交,可以看到生成了一條Channel Rule。
運行process.jpd,輸入substr的值為sub1,可以看到控制臺出現了如下資訊,表明Event Generator已經正常工作:
![](http://dev2dev.bea.com.tw/techdoc/05wi/image/3001.png) 大家可以嘗試將sub1.jpd中的publish節點也修改為通過JMS發送。
通過Event Generator,可以實現多個Weblogic Integration之間的BPM呼叫,因為JMS,FILE,EMAIL等是不受Application的限制,是可以跨系統的,同時,可以通過設定,將多種方式與Channel聯繫起來,Channel的發佈者可以根據自身應用的特點,採取相應的方式,甚至異構應用系統都可以通過FILE,EMAIL等產生Channel,然後被訂閱者接收到。這樣就保證了BPM之間的呼叫建製在松耦合的架構之上,大大增強了應用的靈活性,可擴展性。
|