jBPM3與jBPM4實現對比
jBPM3 vs jBPM4
JBoss Goup 目前已經發布了 jBPM4 Alpha1 版本,在版本 4 中最大的變化就是引入 PVM (流程虛擬機)的概念,而引擎內部的調度算法中重要的 Token 機制,在新版中也去掉了,縱觀整個代碼,變化可以說非常的大,筆者接下來就試着來比較一下這種變化,讓大家能有個直觀的認識。當然 Jbpm4 在 JBoss 的官方網站上的 Road map 中,在今年的 7 月 1 號纔會發佈第一個正式版本,因此後續可能還會有變化。
1、 流程定義對象的變化:
Jbpm3 流程定義對象關係圖:
圖一 jbpm3流程定義對象關係圖
從上圖我們可以看出這 jbpm3 中, GraphElement 是流程圖中所有流程元素的父對象,而整個流程是由 ProcessDefinition 、 Node 、 Transition 三個主要對象構成;
圖二 PVM 實體對象關係圖
從上圖可以看出,由於 PVM 概念的引入,所以在 jbpm3 中的 Graph 包在 jbpm4 中被移除了。在 pvm 中,在設計期,所有節點元素的父類爲 ProcessElementImpl ,流程的主要組成元素 Nodelmpl 、 TransitionImpl 、 ProcessDefinitionImpl 、 EventImpl 則都直接或間接繼承自 ProcessElementImpl 。在運行期: jbpm4 把流程的運行期行爲定義爲執行行爲( ExecutionImpl )及原子操作行爲( AtomicOperation ,其具體實現爲 ExecuteNode 、 ProceedToDestination 、 TakeTranstion 、 MoveToParentNode 、 MoveToChildNode 、 signal ),其中 ExecutionImpl 是流程實例、活動實例、事件監聽器的所有執行期行爲的實現類。
圖三 jpdl 運行期活動實體對象關係圖
上圖是 jbpm4 在運行期的活動實例對象關係圖,從圖中我們可以看出,在運行期, jbpm4 中定義了兩個活動接口 Activity 和 ExternalActivity ,其中 ExternalActivity 繼承自 Activity 。 Activity 是所有自動活動節點的父接口,其實現類爲 JpdlActivity ,而 JpdlActivity 又衍生出了、 StartActivity 、 JoinActivity 、 ForkActivity 、 EndActivity 、 CreateTimerActivity 、 JavaActivity 、 EsbActivity 等實例活動對象。而 ExternalActivity 是具有等待狀態的活動( StateActivity )父接口,像人工活動 TaskActivity 就是實現了此接口。
2、 核心引擎的調度算法
Jbpm3 的核心調度算法是基於 Token 機制的,在運行期這個 Token 在 Node Instance 之間流轉,依靠 Token 的觸發來推進流程。具體的調度機制,可參加胡長城的文章( http://blog.csdn.net/james999/archive/2007/09/02/1769592.aspx );其實這個 Token 來自於 Pertri-net ,感興趣的讀者可以去看 Pertri-net 中的 Token 及 Place 。
圖四 jbpm3引擎調度圖
Jbpm4 則去掉了 Token ,那麼它的核心調度機制是怎樣實現的呢?
圖五 jbpm4流程啓動序列圖
圖六 jbpm4 流程推進序列圖
圖五是在 jbpm4 中啓動一個流程實例的執行序列圖,圖六是節點推進的執行序列圖,從上面兩個圖中我們可以看到核心的調度是依據 Execution 的轉移來實現的( ExecutionImpl 可以是 ActivityExecution 、 ClientProcessInstance 、 EventListenerExecution 的實例), Execution 實際上就是取代了 Jbpm3 中的 Token , Execution 的轉移實際上就是根據狀態機的變遷( ActivityExecution 、 ClientProcessInstance 、 EventListenerExecution 實例之間的切換)加上調用相應的原子操作: ExecuteNode 、 MoveToChildNode 、 MoveToParentNode 、 ProceedToDesitination 、 Signal 、 TakeTransition (詳見 pvm/internal/model/op 包下的相關類)來實現的。所以 Execution 實例的集合及有向圖實際上就是運行期的路徑。
3、 Event-Action 機制的變化
在 jbpm3 中是基於 Event-Action 機制來實現事件與動作的觸發的,但是在 jbpm4 中則採用觀察者模式來觸發事件的。所有用戶自己定義的動作,全部要實現 EventListener 接口,這些動作作爲監聽者(就是事件 Event 的觀察者 Observer )註冊到相應的流程定義對象上( ProcessElement 或者 Node ),而事件 Event 則作爲被觀察的對象(實際上就是 Observerable ),實際上在 jbpm4 中專門定義出了一個對象 ObservableElementImpl ,流程定義中的 NodeImpl 、 TransitionImpl 、 ProcessDefinitionImpl 均繼承自此對象,因此這些元素本身就可以作爲 Observerable 而被觀察者來監控。
4、 客戶端接口的變化
在jbpm4中對客戶端的接口統一爲7個服務接口:ProcessService、ExecutionService、CommandService 、TaskService 、ManagementService、HistoryService、IdentityService,這7個接口可以從ProcessEngine接口中獲得,jbpm4在啓動的過程中由JbpmConfiguration負責構建引擎。
Ø ProcessService-流程定義的服務接口,包括對流程定義的部署、查詢、刪除操作;
Ø ExecutionService-執行服務接口,包括啓動流程、實例推進、設置變量等操作;
Ø CommandService-Command模式的服務接口,實際上就是將客戶端的請求全部封裝在一個調用接口中,然後由這個接口去調用Command接口的衆多實現(StartExecutionCmd、SignalCmd、SetVariablesCmd、GetTimersCmd、DeployCmd、NewTaskCmd、SubmitTask、ExecuteJobCmd等等,具體可參加pvm/internal/cmd,task/internal/cmd包及其它包下實現Command接口的類),這是典型的Command模式的應用,感興趣的讀者可以去了解設計模式中的Command模式;
Ø TaskService-人工活動的服務接口,包括對任務的創建、提交、查詢、保存、刪除等操作;
Ø ManagementService-web管理控制檯的服務接口,目前只有獲得消息及計時器的接口實現;
Ø HistoryService-目前有對歷史庫中的流程實例、活動實例進行查詢、某個流程定義中的所有活動的平均持續時間、某個流程定義中的某個活動實例的轉移的執行次數
Ø IdentityService-用戶、組、成員關係的相關操作方法
5、 歷史庫的加入
jBPM3中數據庫設計一直是我比較詬病的地方,尤其是其實例數據庫沒有設計歷史庫的概念並按照辦結狀態將運行結束的實例數據歸入歷史庫,在這種情況下它的實例數據庫就會隨着時間而無限膨脹,這就阻礙了它的真實應用,而在jBPM4的最新代碼中(注意Alpha1還沒有出現),歷史庫的相關功能代碼竟然出現了!詳見ExecutionImpl最新代碼中的fireHistoryEvent方法及一系列的historyXXX方法。在ActivityBehaviour的execute方法中加入了historyTaskStart方法的調用、signal方法中加入了historyTaskEnd方法的調用,而以上2個方法在ExecutionImpl中都是以歷史事件(HistoryEvent有4個實現子類ProcessInstanceStart、ProcessInstanceEnd、ActivityStart、ActivityEnd分別用作流程實例的創建結束期、活動實例的創建結束期的歷史數據處理)的觸發機制來實現的,也就是在整個流程實例執行的過程中,都加入了對將運行數據存入歷史庫的歷史事件(HistoryEvent)的觸發。這樣實例列表的查詢可以只查詢歷史庫。不過這裏很遺憾的是,這個事件沒有同時清除運行庫的數據,這樣還是會造成運行庫的無限膨脹問題。