<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 26,  comments - 7,  trackbacks - 0

    作者: JeffreyHsu


    盡管jbpm非常強大,是目前最適合商業化的開源工作流引擎,可以開發出復雜的流程,但是特別遺憾的是并不支持并發子流程(multiple-subprocess)
    有一次我需要做一個復雜的流程,主流程里要求同時啟動多個并發執行的子流程,并且子流程的數目和啟動的時間都不確定,當所有子流程都結束以后,主流程才繼續執行。我們知道jbpm里有子流程的設定,有專門的節點ProcessState來處理,但是后來發現無論如何也實現不了多子流程并發執行,后來看其源碼知道因為subprocess是作為ProcessState的一個屬性,也就是說ProcessState只能包含一個subprocess的定義,并且最重要的是processInstance.getRootToken()和子流程相關的只有createSubProcessInstance, getSubProcessInstance, setSubProcessInstance三個方法,這意味著主流程的rootToken只能設置一個子流程,jbpm并不直接支持多子流程。
    那么我們就必須用一個變通的方法來實現,“并發”很自然的讓我們想到了fork,但是這里的fork不能搭配join來使用,具體原因,將在后面討論。
    下面先給出流程圖:

    state節點用來啟動子流程(實際應用可以換成Task-Node),state進入fork后同時進入兩個分支,一條去啟動子流程,另一條回到自己,這樣表面看來state沒有動,而同時你又可以啟動第2個,第3個……子流程,需要注意的是第2條子流程和第1個子流程并不處于同一級上,而比第一個子流程低一級,具體請看后面一張圖就明白了,分解后的:

    從圖中我們可以看到后一個子流程的整棵樹是前一個子流程的兄弟,但是在業務級上是并發的效果,已經實現我們前面的需求。

    現在來說說為什么不能用join而直接用end,因為會產生一個問題,state3和sub process 2都到達了join以后,state2下面的fork就結束了,就會立刻越過join到達end,而sub process 1即使執行完畢到達了join卻仍然在傻傻等待著他的兄弟分支也到達join(而實際上它已經自跑到end去了)一同結束,這樣sub process 1就會永遠停在join動彈不得,業務無法進行。

    這是我的一個解決方案,但還有一個問題,雖然全部的子流程都能結束,主流程也能結束,但因為沒有join,主流程的rootToken仍然停留在fork節點上。目前我尚不知如何解決,希望各位大家能提出其他更好的解決辦法。
    初學jbpm,水平有限,有不當之處還請高手斧正

    最后附上demo代碼供參考:

    代碼
    1.   
    2. import static org.junit.Assert.*;   
    3.   
    4. import org.jbpm.graph.def.ProcessDefinition;   
    5. import org.jbpm.graph.exe.ProcessInstance;   
    6. import org.jbpm.graph.exe.Token;   
    7. import org.jbpm.graph.node.ProcessState;   
    8. import org.junit.Before;   
    9. import org.junit.Test;   
    10.   
    11. public class MultiProcessTest {   
    12.     private ProcessDefinition superProcessDefinition;   
    13.   
    14.     private ProcessDefinition subProcessDefinition;   
    15.   
    16.     @Before   
    17.     public void setUp() throws Exception {   
    18.         superProcessDefinition = ProcessDefinition.parseXmlString(   
    19.                 "<process-definition name='super'>" +                
    20.                 "  <start-state name='start'>" +   
    21.                 "    <transition to='state' />" +   
    22.                 "  start-state>" +   
    23.                 "  <state name='state'>" +   
    24.                 "    <transition name='create sub' to='fork' />" +   
    25.                 "    <transition name='end' to='end' />" +   
    26.                 "  state>" +   
    27.                 "  <fork name='fork'>" +   
    28.                 "    <transition name='back' to='state' />" +   
    29.                 "    <transition name='go to sub' to='sub process' />" +   
    30.                 "  fork>" +   
    31.                 "  <process-state name='sub process'>" +   
    32.                 "    <sub-process name='sub' />" +   
    33.                 "    <transition to='end' />" +   
    34.                 "  process-state>" +   
    35.                 "  <end-state name='end' />" +   
    36.                 "process-definition>");   
    37.            
    38.         subProcessDefinition = ProcessDefinition.parseXmlString(   
    39.                 "<process-definition name='sub'>" +                          
    40.                 "  <start-state name='start'>"  +   
    41.                 "    <transition to='wait' />" +   
    42.                 "  start-state>" +                         
    43.                 "  <state name='wait'>" +   
    44.                 "    <transition to='end' />" +   
    45.                 "  state>" +              
    46.                 "  <end-state name='end' />" +   
    47.                 "process-definition>");   
    48.         ProcessState processState = (ProcessState) superProcessDefinition   
    49.                 .getNode("sub process");   
    50.         processState.setSubProcessDefinition(subProcessDefinition);   
    51.     }   
    52.   
    53.     @Test   
    54.     public void testMultiProcesses() {   
    55.         ProcessInstance pi = new ProcessInstance(superProcessDefinition);   
    56.   
    57.         // 啟動一個主流程   
    58.         pi.signal();   
    59.         assertEquals("state", pi.getRootToken().getNode().getName());   
    60.   
    61.         // 進入分支,此處將進入子流程   
    62.         pi.signal("create sub");   
    63.         // 主流程token將停留在fork節點上   
    64.         assertEquals("fork", pi.getRootToken().getNode().getName());   
    65.   
    66.         // fork分為兩支,其中一支的節點停留在ProcessState上   
    67.         Token subProcessToken1 = pi.getRootToken().getChild("go to sub");   
    68.         ProcessInstance subPi1 = subProcessToken1.getSubProcessInstance();   
    69.         assertEquals("wait", subPi1.getRootToken().getNode().getName());   
    70.   
    71.         // 另一支返回了state節點,實際上并沒有返回,這個state節點不同于先前的state,它們并不在同一個path中   
    72.         Token stateToken1 = pi.getRootToken().getChild("back");   
    73.         assertEquals("state", stateToken1.getNode().getName());   
    74.            
    75.         // 再次進入fork,啟動第二個子流程   
    76.         stateToken1.signal("create sub");   
    77.         ProcessInstance subPi2 = stateToken1.getChild("go to sub")   
    78.                 .getSubProcessInstance();   
    79.         // 雖然都是子流程,但它們并不相同,在邏輯上是屬于并發的無關系的子流程   
    80.         assertFalse(subPi1.equals(subPi2));   
    81.         // 結束第二個子流程   
    82.         subPi2.signal();   
    83.         assertTrue(subPi2.hasEnded());   
    84.         assertFalse(pi.hasEnded());   
    85.   
    86.         // 結束第一個子流程,但主流程仍未結束   
    87.         subPi1.signal();   
    88.         assertTrue(subPi1.hasEnded());   
    89.         assertFalse(pi.hasEnded());   
    90.            
    91.         // 結束第二個子流程中的state,第一子流程的back分支結束,從而主流程也結束   
    92.         Token stateToken2 = stateToken1.getChild("back");   
    93.         assertEquals("state", stateToken2.getNode().getName());   
    94.         assertFalse(stateToken1.hasEnded());   
    95.         assertFalse(pi.hasEnded());   
    96.         stateToken2.signal("end");   
    97.            
    98.         assertTrue(stateToken1.hasEnded());   
    99.         assertTrue(subPi1.hasEnded());   
    100.         assertTrue(pi.getRootToken().getChild("back").hasEnded());   
    101.         assertTrue(pi.getRootToken().getChild("go to sub").hasEnded());   
    102.         // 主流程結束了   
    103.         assertTrue(pi.hasEnded());   
    104.         // 雖然主流程已經結束了,但是因為子流程沒有join,所以其rootToken仍然停留在fork上   
    105.         assertEquals("fork", pi.getRootToken().getNode().getName());   
    106.         // 第二個子流程到達的end和主流程中的end并不是同一個節點   
    107.         assertTrue(!pi.getRootToken().getNode().equals(stateToken2.getNode()));   
    108.     }   
    109. }   
    posted on 2007-09-11 17:48 jbpm 閱讀(1023) 評論(0)  編輯  收藏 所屬分類: jbpm深入研究

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲免费人成在线视频观看| 国产一卡二卡≡卡四卡免费乱码| 亚洲精品成人片在线观看精品字幕| 麻豆va在线精品免费播放| 国产精品久久久久影院免费| 亚洲AV无码专区国产乱码不卡| 波多野结衣免费视频观看| 日韩欧美亚洲国产精品字幕久久久| 日韩精品免费一区二区三区| 亚洲精品乱码久久久久久V| 国产青草视频在线观看免费影院| 美女无遮挡免费视频网站| 国产成人亚洲精品91专区手机| 免费人成在线观看视频高潮| 亚洲一区二区三区四区在线观看| 18pao国产成视频永久免费| 亚洲va在线va天堂成人| 日韩高清免费观看| 曰批全过程免费视频观看免费软件| 亚洲女人被黑人巨大进入| 日韩av无码免费播放| 亚洲一区在线观看视频| 国产免费无遮挡精品视频| 日本高清不卡中文字幕免费| 亚洲精品国产品国语在线| 国产免费的野战视频| 国产精品亚洲天堂| 精品久久久久久亚洲| 亚洲免费闲人蜜桃| 国产99久久亚洲综合精品| 亚洲AV永久无码精品水牛影视| 国产卡二卡三卡四卡免费网址 | 毛片免费观看网址| 免费一级特黄特色大片| 亚洲国产一区在线| 国产真人无遮挡作爱免费视频| 国产免费AV片在线观看| 亚洲国产日韩视频观看| 亚洲精品狼友在线播放| 好大好硬好爽免费视频| 国产午夜无码精品免费看动漫|