這一章解釋了流程定義的基礎,流程虛擬機給予的功能 以及活動實現是如何構建的。 同時,客戶端API被用來執行包含了那些活動實現的流程。
5.1. ActivityBehaviour
PVM庫沒有包含完整的流程結構。 作為替代的是,活動的運行時行為被委派給一個ActivityBehaviour。 換句話講,ActivityBehaviour是一個接口, 它用來在純java環境實現流程結構的運行時行為。
public interface ActivityBehaviour extends Serializable {
void execute(ActivityExecution execution) throws Exception;
}
當一個活動行為被調用時,它就處于執行傳播的全部控制中。 換句話說,一個活動行為可以決定下一步應該執行什么執行。
比如,可以使用execution.take(Transition)獲得一個轉移,
或者使用execution.waitForSignal()進入等待階段。 萬一活動行為沒有調用任何上述的執行傳播方法, 執行將
按默認方式執行。
5.2. ActivityBehaviour實例
我們會啟動一個非常原始的hello world例子。 一個Display活動會將一條信息打印到控制臺:
public class Display implements ActivityBehaviour {
String message;
public Display(String message) {
this.message = message;
}
public void execute(ActivityExecution execution) {
System.out.println(message);
}
}
讓我們使用這個活動構建我們第一個流程定義:
Display實例流程
圖 5.1. Display實例流程
TODO add ProcessBuilder example code
現在我們可以像下面這樣執行流程:
Execution execution = processDefinition.startExecution();
startExecution的調用會在控制臺打印hello world:
hello
world
一個總是值得提醒的事情是活動可以使用屬性進行配置。 在Display例子中,你可以看到message屬性在兩種使用方法中配置的不同。
通過配置屬性,我們可以寫出可復用的活動。 它們可以在以后每次使用在流程中都進行不同的配置。 這是一個基本的部分,
將流程語言構建在流程虛擬機之上。
其他需要解釋的部分是 這個活動實現沒有包含任何執行傳播的功能。 當一個新流程實例啟動時, 執行會定位到初始活動,那個活動會被執行。
Display.execute方法用來決定默認的執行傳播。 具體的,這意味著活動自己 沒有調用任何執行傳播的方法。
那種情況下,默認的傳播會執行。默認傳播會選擇第一個轉移,如果這個轉移存在的話。 如果沒有,它會結束這個執行。
這揭示了為什么a活動和b活動都被執行, 而在b活動執行完執行會停止。
關于默認流程行為的更多細節可以 在第 7.3 節 “默認執行行為”找到。
5.3. ExternalActivityBehaviour
外部活動是負責流程執行由外部轉移進來的活動, 外部的意思是來自流程系統的外部。 這意味著這個執行流程對于系統來說,這是一個等待狀態。 這個執行會一直等待到外部觸發器調用。
為了處理外部觸發器,ExternalActivityBehaviour 為ActivityBehaviour添加了一個方法:
public interface ExternalActivity extends Activity {
void signal(Execution execution,
String signal,
Map<String, Object> parameters) throws Exception;
}
就像普通的活動,當一個執行到達一個活動, 外部活動行為的execute方法會被調用。
在外部活動中,execute方法會傳遞另一個系統的響應, 然后通過調用execution.waitForSignal() 進入等待狀態。
比如在execute方法中,響應可能是由一個人傳入, 通過在任務管理系統中創建一個任務入口, 然后等待到這個人完成這個任務。
一旦活動行為已經處于等待狀態, 然后執行會等待到調用signal方法。 執行會委派signal給ExternalActivityBehaviour對象 分配給當前的活動。
所以活動的signal方法 會在等待期間,在執行獲得一個外部觸發器的時候調用。 signal方法中,響應會傳遞給后面的流程執行。 比如,當一個人完成了一個任務,任務管理系統 會在執行中調用signal方法。
一個signal可選擇使用signal名字和一個參數map。 活動行為攔截signal和參數的最常用方式是 signal對應選擇的外出轉移, 參數作為執行中的變量。但那些只是例子, 它一直等到活動使用singal和它期望的參數。
5.4. ExternalActivity實例
這里是一個簡單等待狀態實現的第一個例子:
public class WaitState implements ExternalActivity {
public void execute(ActivityExecution execution) {
execution.waitForSignal();
}
public void signal(ActivityExecution execution,
String signalName,
Map<String, Object> parameters) {
execution.take(signalName);
}
}
execute方法調用execution.waitForSignal()。 execution.waitForSignal()的調用 會使流程執行進入等待狀態, 直到一個外部觸發器出現。
signal方法使用signal參數對應的轉移名稱 來選擇轉移。所以當一個執行獲得一個外部觸發器, signal名稱被攔截,作為外部轉移的名稱, 執行會被傳播到那個轉移上。
這里是從a到b有一個轉移的相同的流程。 這時候,兩個活動的行為都是WaitState。
外部活動實例流程
圖 5.2. 外部活動實例流程
ClientProcessDefinition processDefinition = ProcessFactory.build()
.activity("a").initial().behaviour(new WaitState())
.transition().to("b")
.activity("b").behaviour(new WaitState())
.done();
讓我們為流程定義啟動一個新流程實例:
ClientExecution execution = processDefinition.startProcessInstance();
啟動這個流程會執行a中的WaitState活動。 WaitState.execute會調用
ActivityExecution.waitForSignal。
所以當processDefinition.startProcessInstance()返回, 執行會一直處在a活動。
assertEquals("a", execution.getActivityName());
然后我們提供了外部觸發器, 通過調用signal方法。
execution.signal();
execution.signal()會委派給當前活動。 所以在這種情況下就是a活動里的
WaitState活動。WaitState.signal會調用 ActivityExecution.take(String
transitionName)。 當我們沒有提供一個signal名稱,第一個名字是null會被選中。
我們指定的a的唯一轉移沒有名字,所以會選中這個。 然后這個轉移指向b。 當執行到達b活動, b活動中的WaitState活動會被執行。
就像我們上面看到的,執行會在b一直等待, 這時signal會返回, 離開的執行指向b活動。
assertEquals("b", execution.getActivityName());
jBPM4.0開發指南完整版
http://family168.com/tutorial/jbpm4devguide/html/index.html
posted on 2009-06-25 17:37
卡宴 閱讀(959)
評論(0) 編輯 收藏 所屬分類:
jBPM