Jbpm用戶指南翻譯:第9章 流程建模

 
9.1 綜述
流程定義(process definition)基於有向圖表示了一個業務流程的規格化描述。圖是由節點(node)和轉換(transition)組成的,圖中每個節點都有一個特定類型,節點的類型定義了運行時的行爲。一個流程定義只能有一個開始狀態。
令牌(token)是一個執行路線。令牌是運行時概念,它維護了一個指向圖中節點的指針。
流程實例是(process instance)流程定義的執行。當一個流程實例創建後,一個令牌也爲執行的主要路線創建了,這個令牌被稱爲流程實例的根令牌(root token),它被定位於流程定義的開始狀態。
信號(signal)指示令牌繼續圖的執行。當令牌接收到一個沒有命名的信號,它會經由缺省的離開轉換離開它的當前節點;當一個轉換名稱在信號中被指定時,令牌會經由指定的轉換離開節點。發送到流程實例的信號被委託給根令牌。
令牌進入節點後,節點被執行。節點自己有責任讓圖繼續執行,圖的繼續執行是通過讓令牌離開節點完成的。每個節點類型爲了圖的繼續執行可以實現不同的行爲,如果一個節點不能傳播圖的執行,則被表現爲一個狀態。
動作(Action)是在流程執行中的事件上被執行的java代碼片斷。在軟件需求中,圖是信息交流的一個重要手段,但是圖只是將要生產的軟件的一個視圖(影像),它隱藏了很多技術細節。動作是在圖的表示之外添加技術細節的一種機制,一旦圖被做好,它可以由動作來修飾。主要的事件類型有:進入節點、離開節點、執行轉換。
9.2 流程圖
基本的流程定義是一個由節點和轉換組成的圖,這些信息在processdefinition.xml中表示。每個節點都有一個類型,如state、decision、fork、join等;每個節點有一組離開轉換,可以給離開節點的每個轉換一個名稱來區分它們。例如:下圖顯示了jBay拍賣流程的流程圖。
9.1拍賣流程圖
下面是jBay拍賣流程圖的xml表示:
<process-definition>
 
 <start-state>
    <transition to="auction" />
 </start-state>
 
 <state name="auction">
    <transition name="auction ends" to="salefork" />
    <transition name="cancel" to="end" />
 </state>
 
 <fork name="salefork">
    <transition name="shipping" to="send item" />
    <transition name="billing" to="receive money" />
 </fork>
 
 <state name="send item">
    <transition to="receive item" />
 </state>
 
 <state name="receive item">
    <transition to="salejoin" />
 </state>
 
 <state name="receive money">
    <transition to="send money" />
 </state>
 
 <state name="send money">
    <transition to="salejoin" />
 </state>
 
 <join name="salejoin">
    <transition to="end" />
 </join>
 
 <end-state name="end" />
 
</process-definition>
9.3 節點
流程圖是由節點和轉換組成的,有關圖的以及它的擴展模型的更多信息,請參考“第4章 面向圖的編程”TODO。
每個節點有一個特定類型,節點類型決定了在運行時執行到達節點時將發生什麼。Jbpm有一組你可以使用的預定義的節點類型,另外,你也可以編寫定製代碼來實現你自己指定的節點行爲。
每個節點都有兩個主要責任:首先,它可以執行普通java代碼,典型情況下,java代碼與節點功能是相關的,例如:創建一些任務實例、發送一個通知、更新一個數據庫等;其次節點要負責傳播流程執行。基本上來說,每個節點在傳播流程執行時有以下幾個可選方式:
1.不傳播執行。這種情況下節點表現爲一個等待狀態。
2.經由節點的某個離開轉換傳播執行。這意味着到達本節點的令牌使用API調用executionContext.leaveNode()經由某個離開轉換被傳遞,這時節點作爲一個自動節點,它可以執行一些定製的程序邏輯然後自動繼續流程執行,而沒有等待。
3.創建一個新的執行路徑。節點可以決定創建新的令牌,每個新的令牌表示一個新的執行路徑,並且每個令牌可以通過節點的離開轉換被啓動。這種行爲的一個很關好的例子就是fork節點。
4.結束執行路徑。節點可以決定結束執行路徑,這意味着令牌被結束,執行路徑也就完結了。
5.更一般的情況,節點可以修改流程實例的整個運行時結構。運行時結構是包含一個令牌樹的流程實例,每個令牌表示一個執行路徑,節點可以創建和結束令牌,把每個令牌放在圖中的節點,並且通過轉換啓動令牌。
 
Jbpm像其他任何工作流和BPM引擎一樣,包含一組預實現的節點類型,它們有特定的文檔配置和行爲,但是關於Jbpm和麪向圖的編程基礎(第4章 面向圖的編程TODO)相對於其他來說其獨特之處是對開發者開放模型,開發者可以很容易的編寫自己的節點行爲,並在流程中使用。
這也就是傳統的工作流和BPM系統非常封閉之處,它們通常提供一組固定的節點類型(叫做流程語言),它們的流程語言是封閉的並且執行模型被隱藏在運行環境中。研究工作流模式可以發現,任何流程語言都不足夠強大,我們決定做一個簡單模型,並且允許開發者編寫他們自己的節點類型,而JPDL流程語言則是完全開放的。
接下來我們論述JPDL中非常重要的節點類型。
9.3.2 節點類型task-node
任務節點代表一個或多個被人所執行的任務。因此當執行到達一個任務節點時,任務實例將會在工作流參與者的任務列表中被創建,然後,節點將表現爲一個等待狀態,當用戶執行了他們的任務時,任務的完成會觸發恢復執行,換句話說,這將導致一個新的信號在令牌上被調用。
9.3.3 節點類型state(狀態)
狀態就是一個等待狀態,與任務節點不同的是沒有任務實例在任務列表中被創建,如果流程需要等待一個外部系統,這是有用的。例如,在節點的入口處(通過node-enter時間的動作),可以發送一個消息到外部系統,然後流程進入等待狀態,當外部系統發送一個響應消息時,這可以導致一個token.signal(),用來觸發恢復流程執行。
9.3.4 節點類型decision(決策)
實際上有兩種方式來建模決策,這兩種方式之間的不同是基於“誰”來做決策,可以由流程(請閱讀:在流程定義中指定)來做決策,或者由外部實體來提供決策結果。
當由流程來做決策時,就應該使用決策節點了。有兩個基本的方法來指定決策標準:簡單的方式是在轉換上添加條件元素(condition),條件是返回一個布爾值的beanshell腳本表達式,在運行時,決策節點會循環它的離開轉換(按照xml中指定的順序)並計算每個條件,第一個條件結果返回爲“true”的轉換將被使用。另外一種可選方式是指定一個DecisionHandler的實現,然後決策在java類中被計算並且通過DecisionHandler實現的decide方法返回所選的離開轉換。
當決策是由外部部分(意思是:不是流程定義的一部分)來決定時,你可以使用多個轉換離開一個狀態或等待狀態節點,然後,離開轉換可以被提供到外部,在等待狀態結束後觸發恢復執行,例如Token.signal(String transitionName)和TaskInstance.end(String transitionName)。
9.3.5 節點類型fork(分支)
分支把一個執行路徑分裂成多個併發的執行路徑。默認的分支行爲是爲每個離開分支的轉換創建一個子令牌,並且與到達分支的令牌之間創建一個父子關係。
9.3.6 節點類型join(聯合)
默認的聯合假定到達聯合的所有令牌都是同一父令牌的子令牌,這種情形當使用上面所提到的分支節點、並且當所有由分支創建的令牌到達同一聯合時發生。聯合會結束進入聯合的每個令牌,然後聯合會檢查進入聯合的令牌的父子關係,當所有的兄弟令牌都到達聯合時,父令牌將會通過離開轉換傳播,當仍然還有活動的兄弟令牌時,聯合表現爲一個等待狀態。
node節點類型適用於當你想要在節點中編寫自己的代碼的情形。node類型節點需要一個子元素動作(action),當執行到達節點時動作被執行,你寫在actionhandler中的代碼可以做任何事情,也包括節點必須自己負責傳播執行(參考9.3.1  節點責任)TODO。
如果你想要使用JavaAPI實現一些對業務分析者來說非常重要的功能邏輯,則可以使用node類型節點,通過使用node節點,節點在流程的圖形表示中是可見的。作爲對比,如果邏輯對於業務分析者來說是不重要的,則動作(下面將會介紹)允許你在流程的圖形表示中添加不可見的代碼。
9.4 轉換(Transitions)
轉換有一個源節點和一個目標節點,源節點用from屬性表示,目標節點用to屬性表示。
節點可以有一個任意的名稱,注意:很多Jbpm特性依賴於唯一的轉換名稱,如果有多個轉換有相同的名字,則擁有給定名稱的第一個轉換被使用。如果在一個節點中存在重複的轉換名稱,則Map getLeavingTransitionsMap()方法返回的元素將少於List getLeavingTransitions()方法。
默認的轉換是列表中的第一個轉換。
9.5 動作(Actions)
動作是在流程執行的事件上被執行的java代碼片斷。在軟件需求交流中圖是一種重要的工具,但是圖僅僅是要生產的軟件的一個視圖(影射),它隱藏了很多技術細節,動作是一種在圖形表示之外添加技術細節的機制。一旦圖被做好,它就可以用動作來進行裝飾,這意味着在不改變圖的結構的情況下,java代碼可以與圖關聯。主要的事件類型是進入節點、離開節點、執行轉換。
注意動作被放置在事件與被放置在節點之間的差異。放置在事件中的動作當事件激活時被執行,事件上的動作不能影響流程的控制流,這很像觀察者模式。另一方面,放置在node(參考9.3.7 節點類型node )TODO上的動作則有傳播流程執行的職責(參考9.3.1  節點責任)TODO。
讓我們來看一個事件動作的例子。假設我們要在給點轉換上做數據庫更新,數據庫更新是技術上必須的,但是對於業務分析者來說它是不重要的。
9.2 數據庫更新動作
public class RemoveEmployeeUpdate implements ActionHandler {
 public void execute(ExecutionContext ctx) throws Exception {
    // get the fired employee from the process variables.
    String firedEmployee = (String) ctx.getContextInstance().getVariable("fired employee");
   
    // by taking the same database connection as used for the jbpm updates, we
    // reuse the jbpm transaction for our database update.
    Connection connection = ctx.getProcessInstance().getJbpmSession().getSession().getConnection();
    Statement statement = connection.createStatement();
    statement.execute("DELETE FROM EMPLOYEE WHERE ...");
    statement.execute();
    statement.close();
 }
}
 
<process-definition name="yearly evaluation">
 
 ...
 <state name="fire employee">
    <transition to="collect badge">
      <action class="com.nomercy.hr.RemoveEmployeeUpdate" />
    </transition>
 </state>
 
 <state name="collect badge">
 ...
 
</process-definition>
 
9.5.1 動作配置
有關在processdefinition.xml中怎樣對你定製的動作添加配置以及如何指定配置的更多信息,請參考“16.2.3配置委託”TODO。
9.5.2 動作引用
動作可以指定名稱,命名的動作可以在其他需要指定動作的地方來引用,命名的動作可以作爲子元素被放入流程定義中。
這個特性在你想限制動作重複配置時非常有用(例如,當動作的配置複雜時)。另外一個用處就是執行或調度運行時動作。
9.5.3 事件
事件指定了流程執行中的時刻。Jbpm引擎在圖執行期間會激活事件,這發生在Jbpm計算下一個狀態時(請參閱:處理信號)。事件總是同流程定義中的元素相關,例如流程定義中的一個節點或轉換。大多流程元素可以激活不同類型的事件,例如節點可以激活一個node-enter事件和一個node-leave事件。事件是同動作掛鉤的,每個事件有一個動作清單,當Jbpm引擎激活事件時,清單中的動作被執行。
9.5.4 事件傳播
超狀態在流程定義的元素之間生成一個父-子關係,節點和轉換被包含在作爲父的超狀態裏,最頂級的元素以流程定義作爲父,流程定義沒有父。當一個事件被激活,事件將被向上傳播至父層次,這允許在一箇中心位置可以捕獲到流程中的所有事件以及與事件相關聯的動作。
9.5.5 腳本
腳本是動作執行的beanshell腳本,關於beanshell的更多信息,請參考beanshell站點。默認情況下,所有的流程變量可作爲腳本變量和非腳本變量被寫到流程變量中使用。以下腳本變量也可被使用:
l       executionContext
l       token
l       node
l       task
l       taskInstance
<process-definition>
 <event type="node-enter">
    <script>
      System.out.println("this script is entering node "+node);
    </script>
 </event>
 ...
</process-definition>
variable元素可以作爲腳本的子元素,用來定製默認的加載和存儲變量到腳本的行爲。如果是那樣的話,腳本表達式還必須被放入腳本的子元素expression內。
<process-definition>
 <event type="process-end">
    <script>
      <expression>
        a = b + c;
      </expression>
      <variable name='XXX' access='write' mapped-name='a' />
      <variable name='YYY' access='read' mapped-name='b' />
      <variable name='ZZZ' access='read' mapped-name='c' />
    </script>
 </event>
 ...
</process-definition>
在腳本開始之前,流程變量YYY和ZZZ分別作爲腳本變量b和c將會被腳本所使用,腳本結束之後,腳本變量a的值被存儲到流程變量XXX中。
如果變量的access屬性包含“read”,則流程變量在腳本計算前作爲腳本變量被加載;如果access屬性包含“write”,則在腳本計算後腳本變量將被作爲流程變量存儲。屬性mapped-name可以使流程變量在腳本中以另外一個名字使用,當你的流程變量包含空格或其他非法腳本字符時這很有用。
9.5.6 定製事件
注意,在流程執行期間激活你自己的定製事件是可能的。事件通過組合圖元素(節點、轉換、流程定義、超狀態是圖元素)和事件類型(java.lang.String)被唯一的定義。Jbpm定義了一組可由節點、轉換和其他圖元素激活的事件,但是作爲一個用戶,你可以自由的激活你自己的事件,在動作中、在你自己定製的節點執行中、或者甚至在流程實例執行之外,你都可以調用GraphElement.fireEvent(String eventType, ExecutionContext executionContext),事件類型的名稱可以自由選擇。
9.6 超狀態(Superstates)
超狀態是一組節點,超狀態可以被遞歸嵌套。超狀態可以被用來在流程定義中產生一些層次,例如,一個應用可能要把流程中的所有節點按階段進行分組。動作可以與超狀態事件關聯,結果就是一個令牌在某個給定時間可以存在於多個嵌套的節點,這便於檢查流程是否執行,比如,是否在啓動階段。在Jbpm模型中,你可以任意分組任何節點到一個超狀態。
9.6.1 超狀態轉換
所有離開超狀態的轉換都可以被包含在超狀態的節點裏的令牌使用,轉換也可以到達超狀態,如果那樣的話,令牌將被重定向到超狀態中的第一個節點。超狀態外部的節點可以擁有指向超狀態內部的轉換,同樣,相反的,超狀態內部的節點也可以擁有指向超狀態外部或超狀態自己的轉換。超狀態還可以擁有對它自己的引用。
9.6.2 超狀態事件
有兩個只有超狀態纔有的事件:superstate-enter和superstate-leave。無論通過哪個轉換進入或離開節點,這些事件都會被激活。在超狀態內部令牌執行轉換時,這些事件不會被激活。
9.6.3 分級命名
節點在它的範圍之內必須被唯一命名,節點的範圍是它自己的節點集合,流程定義和超狀態都是節點集合。在指向超狀態內部節點時,你必須指定相對關係,用(/)隔開節點名稱,用“..”指向上一層次。下面的例子展示了怎樣指向一個超狀態內部的節點:
<process-definition>
 ...
 <state name="preparation">
    <transition to="phase one/invite murphy"/>
 </state>
 <super-state name="phase one">
    <state name="invite murphy"/>
 </super-state>
 ...
</process-definition>
下面的例子展示了怎樣向上指向超狀態層次:
<process-definition>
 ...
 <super-state name="phase one">
    <state name="preparation">
      <transition to="../phase two/invite murphy"/>
    </state>
 </super-state>
 <super-state name="phase two">
    <state name="invite murphy"/>
 </super-state>
 ...
</process-definition>
 
9.7 異常處理
Jbpm的異常處理機制僅僅集中於java異常,圖本身的執行不會導致問題,只有在執行委託類時纔會導致異常。
在流程定義(process-definitions)、節點(nodes)和轉換(transitions)上,可以指定一個異常處理(exception-handlers)清單,每個異常處理(exception-handler)有一個動作列表,當在委託類中發生異常時,會在流程元素的父層次搜索一個適當的異常處理(exception-handler),當它被搜索到,則異常處理(exception-handler)的動作將被執行。
注意,Jbpm的異常處理機制與java異常處理不完全相似。在java中,一個捕獲的異常可以影響控制流,而在Jbpm中,控制流不會被Jbpm異常處理機制所改變。異常要麼被捕獲,要麼不捕獲,沒有被捕獲的異常被拋向客戶端(例如客戶端調用token.signal()),而被捕獲的異常則是通過Jbpm的exception-handler,對於被捕獲的異常,圖執行仍會繼續,就像沒有異常發生一樣。
注意,在處理異常的動作中,可以使用Token.setNode(Node node)把令牌放入圖中的任何節點。
9.8 流程組合
在Jbpm中依靠process-state來支持流程的組合。process-state是與另外一個流程定義關聯的狀態,當圖執行到達process-state,一個新的子流程實例被創建,並且它與到達process-state的執行路徑相關聯,超流程的執行路徑將會等待,直到子流程實例結束。當子流程實例結束時,超流程的執行路徑將離開process-state並在超流程中繼續圖的執行。
<process-definition name="hire">
 <start-state>
    <transition to="initial interview" />
 </start-state>
 <process-state name="initial interview">
    <sub-process name="interview" />
    <variable name="a" access="read,write" mapped-name="aa" />
    <variable name="b" access="read" mapped-name="bb" />
    <transition to="..." />
 </process-state>
 ...
</process-definition>
這個“hire”流程包含一個產生“interview”流程的process-state,當執行到達“initial interview”,最新版本的“interview”流程的一個新的執行(相當於流程實例)被創建,然後來自“hire”流程的變量“a”被拷貝到來自“interview”流程的變量“aa”,同樣,“hire”流程的變量“b”被拷貝到“interview”流程的變量“bb”。當“interview”流程結束時,只有“interview”流程的變量“aa”被拷貝回“hire”流程的變量“a”。
通常,當一個子流程被啓動,在離開開始狀態的信號被髮出之前,所有擁有“read”存取屬性的變量都被從超流程載入新創建的子流程;當子流程結束時,所有擁有“write”存取屬性的變量都被從子流程拷貝到超流程。variabled元素的mapped-name屬性允許你指定在子流程中將使用的變量名稱。
9.9 定製節點行爲
在Jbpm中很容易編寫你自己的定製節點。爲了創建定製節點,ActionHandler的一個實現必須被編寫,這個實現可以執行任何業務邏輯,也必須包括傳播圖執行的職責。讓我們看一個更新ERP系統的例子:我們將會從ERP系統中讀取一個數量,然後加上一個存儲在流程變量中的數量,再把結果存儲回ERP系統;基於數量的大小,我們必須通過“small amounts”或“big amounts”轉換離開節點。
9.3 更新erp流程示例片斷
public class AmountUpdate implements ActionHandler {
 public void execute(ExecutionContext ctx) throws Exception {
    // business logic
    Float erpAmount = ...get amount from erp-system...;
    Float processAmount = (Float) ctx.getContextInstance().getVariable("amount");
    float result = erpAmount.floatValue() + processAmount.floatValue();
    ...update erp-system with the result...;
   
    // graph execution propagation
    if (result > 5000) {
      ctx.leaveNode(ctx, "big amounts");
    } else {
      ctx.leaveNode(ctx, "small amounts");
    }
 }
}
在定製的節點實現中可以創建和聯合(join)令牌,關於如何做的示例,請簽出Jbpm源碼中fork和join節點的實現部分:-)
9.10 圖執行
Jbpm的圖執行模型基於的是流程定義的解釋和命令鏈設計模式(chain of command pattern)。
解釋流程定義意思是把流程定義存儲到數據庫中,在運行時流程執行期間流程定義信息被使用。需要注意的是:我們使用hibernate的二級緩存來避免在運行時加載流程定義信息,因爲流程定義不會改變(參考流程版本部分),hibernate可以在內存中緩存流程定義。
命令鏈設計模式意味着圖中每個節點負責傳播流程執行,如果一個節點不傳播執行,則它表現爲一個等待狀態。
這個意思是說流程實例開始執行之後一直執行,直到進入一個等待狀態。
令牌代表一個執行路徑,令牌擁有一個指向流程圖中節點的指針,在等待狀態,令牌可以被持久化到數據庫。現在讓我們看看計算令牌執行的算法:當一個信號發送到令牌時執行開始,然後執行通過轉換和節點使用命令鏈設計模式被傳遞。下面是類圖中的相關方法:
9.4 圖執行相關方法
當令牌在節點內時,信號可以被髮送到令牌,發送信號是開始執行的指示。信號必須指定令牌當前節點的離開轉換,默認的是第一個離開轉換。信號發送到令牌,令牌獲取它的當前節點並且調用Node.leave(ExecutionContext, Transition)方法,可以把ExecutionContext看作令牌,因爲ExecutionContext中的主要對象就是一個令牌。Node.leave(ExecutionContext, Transition)方法會激活轉換事件並且調用轉換的目標節點的Node.enter(ExecutionContext)方法,而Node.enter(ExecutionContext)方法會激活node-enter事件並且調用Node.execute(ExecutionContext)方法。每種類型的節點在execute方法中都有它們自己實現的行爲,每個節點有責任通過再調用Node.leave(ExecutionContext, Transition)傳播圖的執行。概括如下:
l       Token.signal(Transition)
l       -->Node.leave(ExecutionContext, Transition)
l       -->Transition.take(ExecutionContext)
l       -->Node.enter(ExecutionContext)
l       -->Node.execute(ExecutionContext)
注意,完成下一個狀態的計算,包括調用動作是在客戶端線程中完成的。一個誤解是所有計算必須在客戶端線程完成,象任何異步調用,你也可以使用異步消息(JMS)來完成。當消息被髮送到與流程實例更新的同一事務中時,所有的同步問題必須小心對待。某些工作流系統在圖的所有節點之間使用異步消息,除了在高吞吐量的環境裏之外,這個算法可以給業務流程性能調整提供更多的控制和靈活性。
9.11 事務劃分
象“9.10圖執行”TODO和“第4章 面向圖的編程”TODO中解釋的那樣,Jbpm在客戶端線程中運行流程,並且自然使用同步。這個意思是說,token.signal()或者taskInstance.end()只有當流程進入一個新的等待狀態時纔會返回。
這裏我們描述的JPDL特性來自於“第13章 異步繼續”的建模觀點。
因爲流程執行可以很容易同事務服務綁定在一起,所以在很多情況下這是一個非常直觀的方法:在一個事務中流程從一個狀態到另一個狀態。
在某些情形,流程中的某個計算會花費很長時間,這個行爲是不受歡迎的,Jbpm包含一個允許以一種異步方式來繼續流程的異步消息系統用來應對這種情況。當然,在java企業應用環境,Jbpm可以被配置爲使用JMS消息代理,用來代替自己所構造的消息系統。
在某些節點,JPDL支持屬性async=“true”,異步節點不會在客戶端線程被執行,而是通過異步消息系統發送一個消息,並且線程被返回給客戶端(意味着是token.signal()或taskInstance.end()返回)。
注意,現在Jbpm客戶端代碼可以提交事務。消息的發送應該與流程的更新在同一事務中完成。因此事務的最後結果是令牌被移動到下一節點(尚未被執行),並且一個org.jbpm.command.ExecuteNodeCommand消息在異步消息系統上被髮送到Jbpm的命令執行器(Command Executor)。
Jbpm的命令執行器從隊列中讀取並執行命令,在org.jbpm.command.ExecuteNodeCommand下,流程通過執行節點被繼續,每個命令在一個獨立的事務中被執行。
因此,爲了異步流程可以繼續,必須需要運行一個Jbpm命令執行器,一個簡單的方法是在你的Web應用中配置CommandExecutionServlet,作爲選擇,你應確保命令執行器線程可以運行於任何其他方式。
作爲一個流程建模者,你不應該被這些異步消息所幹預,主要關注點是事務劃分:默認情況下Jbpm在客戶端事務中運轉,進行全部計算,直到進入一個等待狀態。使用async=“true”在流程中劃分事務。
讓我們看一個例子:
...
<start-state>
 <transition to="one" />
</start-state>
<node async="true" name="one">
 <action class="com...MyAutomaticAction" />
 <transition to="two" />
</node>
<node async="true" name="two">
 <action class="com...MyAutomaticAction" />
 <transition to="three" />
</node>
<node async="true" name="three">
 <action class="com...MyAutomaticAction" />
 <transition to="end" />
</node>
<end-state name="end" />
...
客戶端代碼與流程執行(開始和恢復)相符合,與普通的流程(同步的)一樣:
...start a transaction...
JbpmContext jbpmContext = jbpmConfiguration.createContext();
try {
 ProcessInstance processInstance = jbpmContext.newProcessInstance("my async process");
 processInstance.signal();
 jbpmContext.save(processInstance);
} finally {
 jbpmContext.close();
}
在第一個處理之後,流程實例的根令牌將指向節點one,並且一個ExecuteNodeCommand消息被髮送到命令執行器。
在併發的事務中,命令執行器從隊列中讀取消息,並且執行一個節點,動作可以決定傳播執行或進入一個等待狀態。如果動作決定傳播執行,則當執行到達節點two時事務會被結束,以此類推 
發佈了10 篇原創文章 · 獲贊 0 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章