jBPM4的高級圖形執(zhí)行 流程構(gòu)建
活動可以實現(xiàn)循環(huán),基于轉(zhuǎn)移或活動組合。 循環(huán)可以包含等待狀態(tài)。
為了支持多次自動循環(huán)執(zhí)行,流程虛擬機 把執(zhí)行的傳播從尾部遞歸轉(zhuǎn)換成while循環(huán)。
7.2. 子流程
TODO: 子流程
7.3. 默認(rèn)執(zhí)行行為
當(dāng)一個Activity被用作活動行為, 它可以使用下面的方法從外部控制流程:
◆waitForSignal()
◆take(Transition)
◆end(*)
◆execute(Activity)
◆createExecution(*)
當(dāng)Activity實現(xiàn)用做活動行為, 沒有調(diào)用任何下面的流程傳播方法,然后 在活動執(zhí)行時,執(zhí)行會使用默認(rèn)執(zhí)行行為。
默認(rèn)執(zhí)行行為定義在下面:
◆如果當(dāng)前活動有一個默認(rèn)向外轉(zhuǎn)移,選擇它。
◆如果當(dāng)前活動有一個父活動,回退到父活動。
◆否則,結(jié)束這個執(zhí)行。
流程語言可以重寫默認(rèn)執(zhí)行行為, 通過重寫ExecutionImpl中的 proceed方法。
7.4. 功能活動
活動也可以用作事件監(jiān)聽器,被稱作功能活動。 自動活動的例子是發(fā)送郵件,執(zhí)行數(shù)據(jù)庫更新, 生成pdf,計算平均數(shù),等等。 所有這些都是自動活動,沒有改變執(zhí)行流向。 這里是這些活動如何實現(xiàn):
- public class FunctionalActivity implements Activity, EventListener {
- public void execute(ActivityExecution execution) {
- perform(execution);
- }
- public void notify(EventListenerExecution execution) {
- perform(execution);
- }
- void perform(OpenExecution execution) {
- ...do functional work...
- }
- }
perform方法獲得一個OpenExecution, 這是ActivityExecution和 EventListenerExecution的超類。 OpenExecution沒有提供任何特定目的的方法, 但是依舊是當(dāng)前狀態(tài),流程定義可以通過變量檢驗, 這包含了環(huán)境信息 對應(yīng)流程執(zhí)行。
這些方法其實都不能調(diào)用執(zhí)行傳播方法。 所以在perform方法完成后,執(zhí)行會 執(zhí)行默認(rèn)的方式。
7.5. 執(zhí)行和線程
這一章解釋流程虛擬機如何通過客戶端的線程, 把一個執(zhí)行從一個等待狀態(tài)帶到另一個。
當(dāng)一個客戶調(diào)用一個執(zhí)行的一個方法(比如signal方法)。 默認(rèn),流程虛擬機會使用線程執(zhí)行流程 直到它到達(dá)一個等待狀態(tài)。一旦下一個等待狀態(tài)到達(dá), 這個方法會返回,客戶端的線程就會返回。 這是流程虛擬機操作的默認(rèn)方式。 兩個更多的異步執(zhí)行可以補充默認(rèn)行為: 異步繼續(xù) 和異步命令服務(wù)。
下一個流程會展示基本理論。 它有三個等待狀態(tài)和四個自動活動。
圖 7.1. 有很多順序自動活動的流程。
這里是如何構(gòu)建流程:
- ClientProcessDefinition processDefinition = ProcessFactory.build("automatic")
- .activity("wait 1").initial().behaviour(new WaitState())
- .transition().to("automatic 1")
- .activity("automatic 1").behaviour(new Display("one"))
- .transition().to("wait 2")
- .activity("wait 2").behaviour(new WaitState())
- .transition().to("automatic 2")
- .activity("automatic 2").behaviour(new Display("two"))
- .transition().to("automatic 3")
- .activity("automatic 3").behaviour(new Display("three"))
- .transition().to("automatic 4")
- .activity("automatic 4").behaviour(new Display("four"))
- .transition().to("wait 3")
- .activity("wait 3").behaviour(new WaitState())
- .done();
讓我們和你一起順著流程的執(zhí)行一起走。
- ClientExecution execution = processDefinition.startProcessInstance();
啟動一個新執(zhí)行意味著初始活動被執(zhí)行。 所以如果一個自動活動是初始活動,這意味著***個未命名的向外轉(zhuǎn)移會被立刻選擇。 這些都發(fā)生在startProcessInstance調(diào)用的內(nèi)部。
然而在這種情況下,初始活動是一個等待狀態(tài)。 所以startProcessInstance方法會立刻返回, 執(zhí)行會定位到初始活動'wait 1'。
一個新執(zhí)行會被定為到'wait 1'。
圖 7.2. 一個新執(zhí)行會被定為到wait 1。
然后一個外部觸發(fā)器會執(zhí)行signal方法。
- execution.signal();
像上面解釋的介紹WaitState, signal會導(dǎo)致選擇默認(rèn)的轉(zhuǎn)移。 轉(zhuǎn)移會把執(zhí)行移動到automatic 1活動,并執(zhí)行它。 automatic 1中的Display活動的execute方法, 向控制臺打印一行,它不會 調(diào)用execution.waitForSignal()。 因此,執(zhí)行會通過選擇automatic 1外部的默認(rèn)轉(zhuǎn)移進行執(zhí)行。 在這種狀態(tài),signal方法一直阻塞著。另一個需要考慮的方式是執(zhí)行方法, 像signal會使用客戶端的線程 來攔截流程定義,直到到達(dá)一個等待狀態(tài)。
然后執(zhí)行到達(dá)wait 2, 執(zhí)行WaitState活動。那個方法會調(diào)用 execution.waitForSignal(),這會導(dǎo)致signal方法返回。 線程會返回到調(diào)用signal方法 的客戶端。
所以,當(dāng)signal方法返回時,執(zhí)行定義到wait 2。
一個signal會把執(zhí)行從'initial'帶到'wait 2'。
圖 7.3. 一個signal會把執(zhí)行從initial帶到wait 2。
然后執(zhí)行會等待一個外部觸發(fā)器, 像是一個對象(更準(zhǔn)確的是一個對象圖)在內(nèi)存中, 直到下一個外部觸發(fā)器執(zhí)行signal方法。
- execution.signal();
第二個調(diào)用的signal會直接讓執(zhí)行進入wait 3, 在它返回之前。
第二個signal讓執(zhí)行進入'wait 3'。
圖 7.4. 第二個signal讓執(zhí)行進入wait 3。
使用這個范例的好處是相同的流程定義可以在 客戶執(zhí)行模式中執(zhí)行 (在內(nèi)存內(nèi)不使用持久化),就像在持久化執(zhí)行模式, 依賴應(yīng)用和環(huán)境。
當(dāng)在持久化模式下執(zhí)行一個流程,你如何綁定 流程執(zhí)行到數(shù)據(jù)庫的事務(wù)上。
持久化模式下的事務(wù)超時
圖 7.5. 持久化模式下的事務(wù)超時
在大多情況下,計算工作是流程需要完成的一部分, 在外部觸發(fā)器(紅色部分)之后的部分,其實很少。 一般來說,處理流程執(zhí)行和處理UI傳遞過來的請求 的事務(wù)不會超過一秒。 而業(yè)務(wù)流程中的等待狀態(tài)可能超過幾小時,幾天甚至幾年。 當(dāng)?shù)却隣顟B(tài)啟動后,線索就變得很清晰, 在等待狀態(tài)啟動之前,只有計算工作的完成包含在事務(wù)中。
考慮一下這種方式: "當(dāng)?shù)竭_(dá)審批時,所有的自動流程需要做的是什么, 在流程系統(tǒng)需要等待另一個外部觸發(fā)器之前?"。 除非pdf需要被創(chuàng)建,或大郵件需要被發(fā)送, 大部分時候,它消耗的時間都是可以忽略的。 這就是為什么在默認(rèn)的持久化執(zhí)行模式下, 流程工作在客戶端線程下執(zhí)行。
這個原因也保證著流程同步路徑的情況。 當(dāng)一個執(zhí)行的單獨路徑切分成流程同步路徑, 流程花在計算上的時間是可忽略的。 所以為什么分支或切分活動實現(xiàn)是有意義的, 目標(biāo)持久化模式產(chǎn)生的同步路徑在同一個線程中按順序執(zhí)行。 基本上它們都只是在同一個事務(wù)中的計算工作。 因為分支或切分知道每個執(zhí)行的同步路徑會返回,所以這只能被完成, 當(dāng)出現(xiàn)一個等待狀態(tài)的時候。
因為這里有一個困難的概念需要掌握,我會再次使用其他詞語來解釋它。 從頭再看一次在持久化執(zhí)行模式下被流程執(zhí)行創(chuàng)建出來的它。 如果在一個事務(wù)中,一個執(zhí)行被給與一個外部觸發(fā)器, 那導(dǎo)致執(zhí)行切分成多個執(zhí)行的同步路徑。 然后執(zhí)行在計算上的部分也可以忽略。 生成SQL的部分也可以忽略。 因為所有在同步分支上完成的功能,必須在同一個事務(wù)中完成, 這里一般沒有指針在分支或切分實現(xiàn), 在多個線程中產(chǎn)生執(zhí)行的同步路徑。
為了創(chuàng)建可執(zhí)行流程,開發(fā)者需要確切知道什么是自動活動, 什么是等待狀態(tài),哪些線程會被分配給流程執(zhí)行。 對于畫業(yè)務(wù)流程的業(yè)務(wù)分析人員,事件就很簡單了。 對于他們畫的活動,他們通常只要知道這是一個人或是一個系統(tǒng)響應(yīng)。 但是他們通常不知道如何轉(zhuǎn)換線程和事務(wù)。
所以對于開發(fā)者,***個任務(wù)是分析什么是流程控制的線程中需要執(zhí)行的, 什么是外部的。 查找外部觸發(fā)器是尋找一個流程中的等待狀態(tài)的很好的開始, 就像動詞和名詞可以在構(gòu)建UML類圖中的元素的規(guī)則。
【編輯推薦】



















