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