程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> jBPM4 PVM的流程定義模型與過程調度

jBPM4 PVM的流程定義模型與過程調度

編輯:關於JAVA

完整的jBPM4 PVM介紹發表在《程序員》第8期,這裡截取部分的意思是PVM的過程調度是非常靈活的,PVM提供了一套和token類似的execution過程調度機制,通過對execution的完全操控,節點運行期行為有了無限的可能。

PVM的流程定義模型

首先要說明的是,上圖裡的類全是接口。位於最上層的是ObservableElement,其提供給流程元素以附加Event(事件)的能力。在 ObservableElementImpl裡,它持有一個events的集合屬性。對於流程元素來說,典型的事件有:流程啟動/結束,節點啟動/結束和轉移線執行(take)。

Java代碼

protected Map<String, EventImpl> events;

Event又做了些什麼呢?EventImpl透過EventListenerReference實例的集合持有EventListener實例。這樣在引擎執行過程調度時,就非常容易地通過流程元素本身獲取事件監聽器並在相應的時候執行它們。

Java代碼

protected List<EventListenerReference> listenerReferences;

和傳統的觀察者模式一致,EventListener接口有且只有一個方法:

Java代碼

void notify(EventListenerExecution execution) throws Exception;

緊接著ObservableElement的是CompositeElement,其擴展了ObservableElement接口。先看看它的方法:

Java代碼

List<? extends Activity> getActivities();

  boolean hasActivity(String activityName);

  Activity getActivity(String activityName);

很明顯,它持有了Activity的集合,對於ProcessDefinition來說,這是一件很自然地事情:流程定義包含多個節點定義。重要的是Activity自身華麗的變身:節點定義實現了嵌套,出現了結構塊。看圖說話:

這一設計在jBPM3裡是沒有的,但是在jBPM4裡則必須出現,因為結構塊是BPEL和BPMN裡的重要概念。既然號稱PVM,則必須向BPEL和 BPMN致敬。稍後我們可以看到,結構塊的引入給引擎過程調度增加了很大的復雜度。在jPDL裡,與之對應的實現是group。這是jBPM4流程定義模型的最重要改變。

ProcessDefinition和Activity分別繼承自CompositeElement,Activity和Transition建立起雙向關聯,這三者也是工作流模型裡的標准建模。

PVM的過程調度

jBPM4采用execution來記錄當前流程執行的位置,並通過移動execution來推動流程的流轉。

Java代碼

/** transient cached current activity pointer. persistence is managed in {@link #activityName} */
  private ActivityImpl activity;

  /** transition is not to be made persistable by default */
  protected TransitionImpl transition;

execution通過activity和transition屬性來記錄位置。

execution 是可以嵌套的,即會存在一種父子關系構成樹狀結構,在任何時間,只有葉子execution處於活動狀態。最上層的execution稱為根 execution,jBPM4裡,根execution即為流程實例(在jBPM3裡,記錄流程執行位置的token和流程實例 processInstance是獨立分開的)。

在兩種情況下,execution會產生子execution。一種情況是流程定義裡存在並發路徑,此時execution會根據並發的路徑個數產生相應的子execution,子execution執行完畢並匯聚後則會觸發它們的父execution繼續流轉。另外一種情況是節點定義存在自己的變量定義和時間服務定義,則執行該節點時會為該節點產生一個獨立的子execution,產生該execution的目的在於使得該節點擁有獨立的作用域,這個子execution也被稱為scope execution。節點執行完畢後,與之關聯的scope execution將會被移除,同時,父execution被重新激活流轉。

1、 execution的移動

execution的移動操作被封裝在atomicOperation裡。execution通過執行atomicOperation來推動其的轉移。目前移動execution的atomicOperation有7種,如下圖所示:

ExecutionActivity 執行節點定義的運行期行為。節點的運行期行為委派給ActivityBehaviour實現,當需要對節點行為進行擴展時,需要實現 ActivityBehaviour接口。jBPM4存在兩個對節點行為進行擴展的接口,分別是ActivityBehaviour和 ExternalActivityBehaviour,ActivityBehaviour的execute方法在節點被執行時調用;ExternalActivityBehaviour繼承自ActivityBehaviour,多出一個signal方法,在節點處於等待狀態被觸發流轉時調用。

Java代碼

ActivityBehaviour activityBehaviour = activity.getBehaviour();

activityBehaviour.execute(execution);

Signal執行節點定義的運行期signal方法。

Java代碼

ExternalActivityBehaviour externalActivityBehaviour =   (ExternalActivityBehaviour) activity.getBehaviour();

externalActivityBehaviour.signal(execution,signalName, parameters);

一個典型的signal方法會調用execution的take方法,從而將execution移動至給定的轉移線上。jPDL裡StateActivity類的signal方法:

Java代碼

execution.take(transition);

看看execution的take方法,設置execution位置並執行TransitionEndActivity:

Java代碼

//設置當前execution的位置
setTransition((TransitionImpl) transition);
   //觸發事件,執行TRANSITION_END_ACTIVITY原子操作
fire(Event.END,getActivity(),AtomicOperation.
TRANSITION_END_ACTIVITY);

TransitionEndActivity銷毀移出節點的scope execution,接著執行TransitionTake:

Java代碼

//如果activity存在scope execution的話,則銷毀,返回父execution
if (activity.isLocalScope()) {
    propagatingExecution = execution.destroyScope(activity);
    }
//父execution執行TRANSITION_TAKE原子操作
propagatingExecution.performAtomicOperation(AtomicOperation.
   TRANSITION_TAKE);

TransitionTake觸發轉移線的take事件,並執行TransitionStartActivity:

Java代碼

execution.fire(Event.TAKE,transition,AtomicOperation.
    TRANSITION_START_ACTIVITY);

TransitionStartActivity設置execution位置為目標節點,創建scope execution並執行ExecutionActivity:

Java代碼

//設置當前execution的位置
execution.setActivity(activity);

ExecutionImpl propagatingExecution = execution;
//如果activity存在scope的話,則創建scope execution
   if (activity.isLocalScope()) {
     propagatingExecution = execution.createScope(activity);
}

propagatingExecution.setTransition(null);
//scope execution執行EXECUTE_ACTIVITY原子操作
propagatingExecution.performAtomicOperation(AtomicOperation.
   EXECUTE_ACTIVITY);

上述5種原子操作構成了一個完整的execution節點間移動過程,分別是:執行節點、觸發流轉、結束源節點、執行轉移線和開始目標節點。如果節點是自動節點(沒有等待狀態),則觸發流轉(signal)這一步操作不會執行。

存在結構塊的情況下,TransitionEndActivity會依次觸發父節點的結束事件,前提是下一個目標節點未被父節點所包含,如果包含,則屬於結構塊內的節點移動;TransitionStartActivity會依次觸發父節點的開始事件,前提同樣是上一個源節點未被該父節點所包含,不屬於結構塊內的節點移動。

MoveToParentActivity使用在節點執行或signal時沒有指定傳播方式,同時又找不到移出的轉移線時,會去執行父節點的signal操作。MoveToChildActivity使用在節點含有子節點時,將execution轉移至子節點執行。這兩種原子操作共同構成了進入和結束結構塊時execution的移動行為。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved