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

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

    從圖中我們可以看到后一個子流程的整棵樹是前一個子流程的兄弟,但是在業(yè)務(wù)級上是并發(fā)的效果,已經(jīng)實現(xiàn)我們前面的需求。

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

    這是我的一個解決方案,但還有一個問題,雖然全部的子流程都能結(jié)束,主流程也能結(jié)束,但因為沒有join,主流程的rootToken仍然停留在fork節(jié)點上。目前我尚不知如何解決,希望各位大家能提出其他更好的解決辦法。
    初學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節(jié)點上   
    64.         assertEquals("fork", pi.getRootToken().getNode().getName());   
    65.   
    66.         // fork分為兩支,其中一支的節(jié)點停留在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節(jié)點,實際上并沒有返回,這個state節(jié)點不同于先前的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.         // 雖然都是子流程,但它們并不相同,在邏輯上是屬于并發(fā)的無關(guān)系的子流程   
    80.         assertFalse(subPi1.equals(subPi2));   
    81.         // 結(jié)束第二個子流程   
    82.         subPi2.signal();   
    83.         assertTrue(subPi2.hasEnded());   
    84.         assertFalse(pi.hasEnded());   
    85.   
    86.         // 結(jié)束第一個子流程,但主流程仍未結(jié)束   
    87.         subPi1.signal();   
    88.         assertTrue(subPi1.hasEnded());   
    89.         assertFalse(pi.hasEnded());   
    90.            
    91.         // 結(jié)束第二個子流程中的state,第一子流程的back分支結(jié)束,從而主流程也結(jié)束   
    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.         // 主流程結(jié)束了   
    103.         assertTrue(pi.hasEnded());   
    104.         // 雖然主流程已經(jīng)結(jié)束了,但是因為子流程沒有join,所以其rootToken仍然停留在fork上   
    105.         assertEquals("fork", pi.getRootToken().getNode().getName());   
    106.         // 第二個子流程到達的end和主流程中的end并不是同一個節(jié)點   
    107.         assertTrue(!pi.getRootToken().getNode().equals(stateToken2.getNode()));   
    108.     }   
    109. }   
    posted on 2007-09-11 17:48 jbpm 閱讀(1023) 評論(0)  編輯  收藏 所屬分類: jbpm深入研究

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


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 水蜜桃视频在线观看免费| 免费A级毛片无码A∨中文字幕下载| 亚洲中文字幕无码久久| 又黄又大的激情视频在线观看免费视频社区在线 | 免费日本黄色网址| 国产成人精品久久亚洲高清不卡 | 国产aⅴ无码专区亚洲av麻豆 | 亚洲成a人无码亚洲成www牛牛 | 亚洲中文字幕久久精品无码喷水| 九九九精品视频免费| 免费无码AV电影在线观看| 亚洲精品无码成人片久久| 亚洲影院天堂中文av色| 好大好硬好爽免费视频| 亚洲第一永久在线观看| 三上悠亚电影全集免费| 免费国产精品视频| 亚洲人成网站日本片| 99在线热播精品免费99热| 免费日本黄色网址| 国产免费久久久久久无码| 免费一看一级毛片人| 国产97视频人人做人人爱免费| 最近2019中文免费字幕| 亚洲成人福利网站| 野花香高清视频在线观看免费| 亚洲成年看片在线观看| 无码天堂亚洲国产AV| 午夜视频免费成人| 一级黄色免费毛片| 亚洲人成影院在线| 久久精品中文字幕免费| 亚洲国产精品一区二区久久hs| 一级毛片在播放免费| 久久久综合亚洲色一区二区三区 | 在线看片免费人成视久网| 亚洲av无码无在线观看红杏| 水蜜桃视频在线观看免费播放高清| 亚洲一区二区三区四区在线观看| 美女被cao网站免费看在线看| 91亚洲视频在线观看|