在 WebSphere Process Server 中為新的查詢要求設定自定義屬性

CloudSpace發表於2010-08-19
Xiang Cheng, 軟體工程師, IBM
Zhu Liang, 軟體工程師, IBM
Pei Jian Dong, 軟體工程師, IBM

簡介: 在您開發一個業務流程客戶端程式時,您經常需要在一個流程例項內,通過某些業務資料標準來查詢流程例項、活動和任務。本文向您展示了在 WebSphere Process Server 中,如何通過一個動態方法為流程例項設定自定義屬性來滿足新查詢要求。

簡介

在您開發一個業務流程客戶端程式時,您經常需要在一個流程例項內,通過某些業務資料標準來查詢流程例項、活動和任務。例如,您可能想要在流程例項中尋找與某個 ID 的客戶相關的所有任務。

當您在 WebSphere Integration Developer(以下簡稱為 Integration Developer)設計流程時,可以通過為人工任務設定自定義屬性來實現這個需求。然而,當流程投入使用後,如果新查詢要求需要新的自定義屬性,那麼這招就不靈了。您當然可以使用 WebSphere Process Server(以下簡稱為 Process Server)提供的流程版本控制方法,在新版業務流程中增加新的自定義屬性。然而,使用新的自定義屬性不能對已有的舊版業務流程進行查詢。

本文對熟悉業務流程開發的業務流程設計師和程式設計師有一定的幫助。本文假設您熟悉 Process Server 和用 Integration Developer 開發業務流程應用程式。如果您沒有經驗,我們建議您仔細閱讀 Business Process Management 樣例 & 教程 — 版本 6.1

在本文中,我們假設 Integration Developer V6.1.2 已得到合理安裝。在本文 參考資料 部分,檢視更多資訊。

本文介紹一種動態的方法,該方法使用 Business Process Choreographer(BPC) EJB API 來為正在執行的業務流程例項設定自定義屬性,從而解決此類問題。

我們將利用一個簡單的命令審計流程來說明這個解決方案。樣例流程工作流包括以下典型步驟:

  • 客戶提交一個訂單請求,其中含有使用者和審計人員的資訊。
  • 審計人員批准或拒絕請求。
  • 最後,當審計人員批准或拒絕請求後,系統給客戶一個響應。

樣例和模組將在以下幾節描述。

使用準備好的業務流程按如下方式匯入專案交換檔案:

  1. 下載提供的 OrderDemo.zip 檔案,並將其儲存到一個臨時目錄中。
  2. 在 WebSphere Integration Developer 中,單擊 File -> Import。Import 對話方塊開啟。
  3. 選擇 Project Interchange。
  4. 單擊 Next。Import Project Interchange Contents 視窗開啟(如圖 1 所示)。

    圖 1. Import 對話方塊
    Import 對話方塊

  5. 單擊 “From zip file” 旁邊的 Browse
  6. 瀏覽臨時目錄,選擇第 1 步中下載的壓縮檔案。
  7. 單擊 Open
  8. 選擇您的工作空間目錄作為您的 Project location root
  9. 單擊 Select All
  10. 單擊 Finish

您需要使用與上面相似的步驟,將提供的包含流程資料型別的 OrderDemoLib.zip 匯入工作空間。您將得到如圖 2 所示的專案結構。以下部分將對此做詳細解釋。


圖 2. 流程專案結構
流程專案結構

業務物件和 BPEL 流程

訂單審計流程有兩個必需的業務物件(BO):OrderRequestPersonInfo(見圖 3)。OrderRequest 儲存訂單資訊,包括客戶、審計人員、狀態和商品編號。PersonInfo 包含個人資訊,比如 ID、姓名和地址。


圖 3. 業務物件
業務物件

圖 4 展示了 Integration Developer BPEL 中設計的流程:

  1. Receive 活動是流程的起始點。流程從客戶端收到一個訊息(OrderRequest),接著開始流程。訊息中的資料儲存在一個流程變數(請求)中。
  2. Assign 活動執行該流程所需的資料對映。
  3. Order Info 片段列印訂單資訊。
  4. ApproveOrderRequest 是審計人員批准或拒絕請求的一個人工任務。
  5. Approve 選項根據審計人員的決議決定下一步。系統將使用 Approve ResponseReject Response 片段列印相應的回覆。

    圖 4. 流程
    流程

使用 BPC Explorer 執行樣例

在嵌入 Integration Developer 的測試伺服器上部署了 OrderDemoApp 之後,使用 Business Process Choreographer (BPC) Explorer 執行樣例,步驟如下:

  1. 在 “My Process Templates” 頁面(見圖 5)上選擇 OrderProcess,然後單擊 Start Instance

    圖 5. 流程模板
    流程模板

  2. 填寫 Process Input Message 部分並單擊 Submit (見圖 6)。

    圖 6. Process Input Message
    Process Input Message

  3. My To-dos 頁面(見圖 7)上處理 ApproveOrderRequest 人工任務工作。

    圖 7. My To-dos
    My To-dos

  4. 輸入 Task Output Message(true 表示批准,false 表示拒絕)。單擊 Complete(見圖 8)。

    圖 8. 處理 Task Message
    處理 Task Message

  5. 在控制檯上(見圖 9),您可以看到測試結果(日誌以 Java™ 片段列印)。

    圖 9. 控制檯
    控制檯

一般來說,您需要開發一個客戶端應用程式來啟動和完成流程例項,而不是使用 BPC Explorer。WebSphere Process Server V6 提供 BPC EJB API 來訪問和處理業務流程和人工任務。事實上,有兩個獨立的 API 集合:Business Flow Manager API 和 Human Task Manager API。

當我們建立流程客戶端應用程式時,常常希望定位一個特定的流程例項或人工任務,其業務資料滿足某個標準。例如,可能需要通過特定的訂單號尋找流程例項。

這部分說明了為什麼您需要為查詢要求設定自定義屬性。查詢出任務之前,您需要啟動流程例項。

您可以使用與匯入流程專案的類似的步驟,將提供的 OrderProcessExport.zip 匯入您的工作空間。該專案的所有程式碼片段在本專案後面部分都能找到。

清單 1 顯示了這些使用 Business Flow Manager API 來啟動一個帶有輸入訊息的 “OrderProcess” 例項的程式碼片段。


清單 1. 使用 BPC EJB API 啟動流程
				
// Create the input ClientObjectWrapper
com.ibm.bpe.api.ClientObjectWrapper cow = flows.createMessage(
		processTemplate.getID(), processTemplate.getInputMessageTypeName());
// Get the Input DataObject from the ClientObjectWrapper
DataObject dataObject = (DataObject) cow.getObject();
	
dataObject.setDataObject("request", OrderRequest);
//Initiate process instance
com.ibm.bpe.api.PIID piid = flows.initiate("OrderProcess", cow);

流程例項啟動後,名為 “ApproveOrderRequest” 的人工任務將被啟動,等待審計人員完成。完成任務之前,您需要通過訂單號查詢出任務。清單 2 顯示了使用 Human Task Manager 通過訂單號過濾任務的程式碼片段 。


清單 2. 通過訂單號獲取特定待處理任務
				
QueryResultSet instances = htms.query("DISTINCT TASK.TKIID", 				
 "TASK.NAME='OrderProcess$ApproveOrderRequestTask' AND 
TASK.STATE=TASK.STATE.STATE_READY", null, null, null, null);

while (instances != null && instances.next()) {
	TKIID tkiid = (TKIID) instances.getOID(1);

	ClientObjectWrapper cow = htms.getInputMessage(tkiid.toString());
	DataObject input = (DataObject) cow.getObject();

	if (orderNo.equals(input.getString("orderNo"))) {
		System.out.println("find!!!");
	}
}

您可以在預定義的 BPC 資料庫檢視上執行 SQL 查詢。然而,像在輸入訊息(業務物件)中定義的訂單號這類業務資料,在資料庫檢視中不能查詢。您不得不通過流程的輸入訊息從所有待處理任務中過濾。如果審計人員有很多待處理任務,這個方法將可能導致效能問題。您也需要改進查詢方法和自定義屬性來滿足您的需求。您可以指定業務流程自定義屬性及其所有的基本活動。一個自定義屬性有一個名稱和一個可選值(字串)。BPC 數 據 庫 提 供一個 PROCESS_ATTRIBUTE 檢視,您可以使用該檢視查詢流程人工任務,方法是將訂單號定義為流程自定義屬性。

除了效能問題之外,還有另一個重要的原因:如果在流程的輸入訊息中不包含查詢標準,您就不能用輸入訊息過濾例項。然而您可以用 BPC EJB API 設定標準作為自定義屬性來滿足這類需求 。

根據自定義屬性執行查詢之前,您需要為流程例項設定自定義屬性。

當啟動流程例項時,您可以使用 BPEL 流程中的一個 Java 片段或 BPC EJB API 來設定自定義屬性。下面將分別介紹這兩種方法。

在 Integration Developer 中使用 Java 片 段設定自定義屬性

您可以在流程的開始增加一個 Java 片段。輸入以下設定語句,如圖 10 所示:

setProcessCustomProperty(“orderNo”, orderNo);


圖 10. 使用 Java 片段設定流程自定義屬性
使用 Java 片段設定流程自定義屬性

使用 BPC EJB API 設定自定義屬性

流程例項啟動之後,您也可以使用 BPC EJB API 將訂單號設定為自定義屬性,如清單 3 所示。


清單 3. 使用 BPC EJB API 設定自定義屬性
				
String rderNo = request.getString("orderNo");
if (orderNo != null && !"".equals(orderNo)) {
	bfms.setCustomProperty(piid, "orderNo", orderNo);
}

流程啟動之後,您可以在 BPC Explorer 中檢視自定義屬性,如圖 11所示。


圖 11. 檢查現有流程例項屬性
檢查現有流程例項屬性

您可以使用預定義的資料庫檢視 PROCESS_ATTRIBUTE 查詢自定義屬性,如表 1 所示。


表 1. PROCESS_ATTRIBUT 檢視
列名 型別 註釋
PIID ID 含有一個自定義屬性的流程例項的 ID。
NAME String 自定義屬性的名稱。
VALUE String 自定義屬性值。

清單 4 顯示瞭如何通過自定義屬性查詢待處理任務。


清單 4. 通過自定義屬性查詢待處理任務
				
QueryResultSet instances = htms.query("DISTINCT TASK.TKIID", 
 "WORK_ITEM.OBJECT_ID = TASK.TKIID AND WORK_ITEM.ASSOC_OID = PROCESS_ATTRIBUTE.PIID AND  
 PROCESS_ATTRIBUTE.NAME= 'orderNo' AND PROCESS_ATTRIBUTE.VALUE ='" + orderNo + "' AND 
 (TASK.STATE = TASK.STATE.STATE_READY OR TASK.STATE = TASK.STATE.STATE_CLAIMED ) AND 
 TASK.SUSPENDED = FALSE AND WORK_ITEM.REASON=1 AND WORK_ITEM.OBJECT_TYPE=5 ", 
 null, null, null, null);
			 
if (instances.size() > 0) {
	instances.first();
	TKIID tkiid = (TKIID) instances.getOID(1);
	ClientObjectWrapper cow = htms.getInputMessage(tkiid.toString());
	DataObject input = (DataObject) cow.getObject();
	
}

您可以使用查詢、通過自定義屬性直接獲取訂單號的任務 ID。這將會產生較好的效能。

如果在業務流程執行之後,出現一個新的查詢要求,此時,您該做什麼?例如,您想要根據 customerId 而非 orderNo 查詢流程例項。您需要新增一個新的名為 “customerId” 的自定義屬性來支援新的查詢要求。如您所知,樣例流程是一個長期流程,就是說,可能有多個例項執行在生產伺服器上。這意味著您需要新增新的自定義屬性, 不僅要為新啟動的流程例項新增,也要為伺服器上已存的例項新增。

為新啟動的流程例項設定新自定義屬性

有兩種方法來實現這個要求。您可以實現一個新版業務流程,在 Java 片段中新增新的自定義屬性。對於版本控制方法,參見 Versioning business processes and human tasks in WebSphere Process Server。另一種方法是,為新啟動的流程例項新增新的自定義屬性 customerId。對於第二種方法,您不需要進行流程版本控制。

從這個角度來看,使用 BPC EBJ API 比在 BPEL 流程中設定自定義屬性要好一些。有了 API,您可以根據需求變化動態地新增新的客戶屬性,而不需要對 BPEL 流程進行版本控制。清單 5 顯示瞭如何使用 BPC EJB API 設定一個新的自定義屬性。


清單 5. 為新啟動的例項設定自定義屬性
				
//Initiate the process instance as usual
com.ibm.bpe.api.PIID piid = flows.initiate("orderProcess", cow);
//Set custom property after process instance is initiated.
flows.setCustomProperty(piid, "orderNo",“000001”);
flows.setCustomProperty(piid, "customerId",“C00001”);

現在,您可以根據新的自定義屬性 customerId 來查詢待處理任務,從而滿足新的需求。

為執行中的流程例項設定新自定義屬性

通過使用 BPC EJB API,您可以搜尋執行中的流程例項,併為其新增一個新自定義屬性。清單 6 顯示瞭如何為執行中的例項新增一個新自定義屬性。


清單 6. 為執行中的例項設定自定義屬性
				
QueryResultSet instances = flows.query("DISTINCT PROCESS_INSTANCE.PIID", 
 "PROCESS_INSTANCE.STATE = 2  AND PROCESS_INSTANCE.TEMPLATE_NAME
  ='OrderProcess' ", "", null, null);

while (instances .next())
{
	PIID piid = (PIID) result.getOID(1);
	flows.setCustomProperty(piid, "customerId", customerIdValue);
		 
}

根據自定義屬性查詢待處理任務

就像根據 orderNo 查詢待處理任務那樣,現在,您可以根據 customerId (見清單 7)執行查詢。


清單 7. 根據新的自定義屬性查詢待處理任務
				
QueryResultSet instances = htms.query("DISTINCT TASK.TKIID", "WORK_ITEM.OBJECT_ID 
 = TASK.TKIID AND WORK_ITEM.ASSOC_OID = PROCESS_ATTRIBUTE.PIID AND 
 PROCESS_ATTRIBUTE.NAME= 'customerId' AND PROCESS_ATTRIBUTE.VALUE ='" + customerId 
 + "' AND (TASK.STATE = TASK.STATE.STATE_READY OR TASK.STATE = TASK.STATE.STATE_CLAIMED ) 
 AND TASK.SUSPENDED = FALSE AND WORK_ITEM.REASON=1 AND WORK_ITEM.OBJECT_TYPE=5 ", null, 
 null, null, null);
if (instances.size() > 0) {
	instances.first();
	TKIID tkiid = (TKIID) instances.getOID(1);
	ClientObjectWrapper cow = htms.getInputMessage(tkiid.toString());
	DataObject input = (DataObject) cow.getObject();
	System.out.println("find customerId:" + customerId	+ " orderNo: 
     " + input.getString("orderNo"));
}

您可以測試 OrderProcessExport 專案,這是一個實現了流程例項的啟動和查詢的 Java 客戶端應用程式。將兩個模組 OrderDemoOrderProcessExport 部署到 Integration Developer 中的測試伺服器之後,您可以在 Integration Developer中使用測試模組測試該項功能。


圖 12. 在 Integration Developer 中測試客戶端應用程式
在 Integration Developer 中測試客戶端應用程式

您可以參考函式描述(表 2)來執行測試。


表 2. PROCESS_ATTRIBUTE 檢視
方法名 功能
initProcess 啟動一個新的流程例項。
initProcessWithOrderNo 啟動一個新的流程例項併為該例項設定自定義屬性 orderNo。
initProcessWithCustomerId 啟動一個新流程例項,併為該例項設定自定義屬性 customerId。
queryTodoTaskByOrderNo 根據請求的 orderNo 查詢特定待處理任務。
queryTodoTaskByCustom
PropertyWithOrderNo
根據自定義屬性 orderNo 查詢特定待處理任務。
queryTodoTaskByCustom
PropertyWithCustomerId
根據自定義屬性 cusomerId 查詢特定待處理任務。
addCustomPropertyFor
RunningProcess
為執行中的流程例項新增新的自定義屬性。

基於業務流程的應用程式包括長期例項,這種例項可以執行幾周、幾月、甚至幾年。業務需求隨時間而變化。WebSphere Process Server V6.1 提供一個稱為 “流程版本控制” 的技術,來幫助升級基於業務流程的應用程式,以滿足新環境和業務需求。然而,您還需要修改已有的例項來滿足新的查詢要求。本文介紹了一種動態方法,它使用 Business Process Choreographer EJB API 來為新流程例項和執行中的例項設定自定義屬性,從而滿足新的查詢要求。使用這種方法,您不需要更新流程來新增一個新的自定義屬性。

原文連結:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1006_cheng/1006_cheng.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-671385/,如需轉載,請註明出處,否則將追究法律責任。

相關文章