2006-10-25
jBPM 并发子流程的解决方案与探讨
关键字: 工作流 并发 子流程
尽管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代码供参考:
有一次我需要做一个复杂的流程,主流程里要求同时启动多个并发执行的子流程,并且子流程的数目和启动的时间都不确定,当所有子流程都结束以后,主流程才继续执行。我们知道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代码供参考:
import static org.junit.Assert.*;
import org.jbpm.graph.def.ProcessDefinition;
import org.jbpm.graph.exe.ProcessInstance;
import org.jbpm.graph.exe.Token;
import org.jbpm.graph.node.ProcessState;
import org.junit.Before;
import org.junit.Test;
public class MultiProcessTest {
private ProcessDefinition superProcessDefinition;
private ProcessDefinition subProcessDefinition;
@Before
public void setUp() throws Exception {
superProcessDefinition = ProcessDefinition.parseXmlString(
"<process-definition name='super'>" +
" <start-state name='start'>" +
" <transition to='state' />" +
" </start-state>" +
" <state name='state'>" +
" <transition name='create sub' to='fork' />" +
" <transition name='end' to='end' />" +
" </state>" +
" <fork name='fork'>" +
" <transition name='back' to='state' />" +
" <transition name='go to sub' to='sub process' />" +
" </fork>" +
" <process-state name='sub process'>" +
" <sub-process name='sub' />" +
" <transition to='end' />" +
" </process-state>" +
" <end-state name='end' />" +
"</process-definition>");
subProcessDefinition = ProcessDefinition.parseXmlString(
"<process-definition name='sub'>" +
" <start-state name='start'>" +
" <transition to='wait' />" +
" </start-state>" +
" <state name='wait'>" +
" <transition to='end' />" +
" </state>" +
" <end-state name='end' />" +
"</process-definition>");
ProcessState processState = (ProcessState) superProcessDefinition
.getNode("sub process");
processState.setSubProcessDefinition(subProcessDefinition);
}
@Test
public void testMultiProcesses() {
ProcessInstance pi = new ProcessInstance(superProcessDefinition);
// 启动一个主流程
pi.signal();
assertEquals("state", pi.getRootToken().getNode().getName());
// 进入分支,此处将进入子流程
pi.signal("create sub");
// 主流程token将停留在fork节点上
assertEquals("fork", pi.getRootToken().getNode().getName());
// fork分为两支,其中一支的节点停留在ProcessState上
Token subProcessToken1 = pi.getRootToken().getChild("go to sub");
ProcessInstance subPi1 = subProcessToken1.getSubProcessInstance();
assertEquals("wait", subPi1.getRootToken().getNode().getName());
// 另一支返回了state节点,实际上并没有返回,这个state节点不同于先前的state,它们并不在同一个path中
Token stateToken1 = pi.getRootToken().getChild("back");
assertEquals("state", stateToken1.getNode().getName());
// 再次进入fork,启动第二个子流程
stateToken1.signal("create sub");
ProcessInstance subPi2 = stateToken1.getChild("go to sub")
.getSubProcessInstance();
// 虽然都是子流程,但它们并不相同,在逻辑上是属于并发的无关系的子流程
assertFalse(subPi1.equals(subPi2));
// 结束第二个子流程
subPi2.signal();
assertTrue(subPi2.hasEnded());
assertFalse(pi.hasEnded());
// 结束第一个子流程,但主流程仍未结束
subPi1.signal();
assertTrue(subPi1.hasEnded());
assertFalse(pi.hasEnded());
// 结束第二个子流程中的state,第一子流程的back分支结束,从而主流程也结束
Token stateToken2 = stateToken1.getChild("back");
assertEquals("state", stateToken2.getNode().getName());
assertFalse(stateToken1.hasEnded());
assertFalse(pi.hasEnded());
stateToken2.signal("end");
assertTrue(stateToken1.hasEnded());
assertTrue(subPi1.hasEnded());
assertTrue(pi.getRootToken().getChild("back").hasEnded());
assertTrue(pi.getRootToken().getChild("go to sub").hasEnded());
// 主流程结束了
assertTrue(pi.hasEnded());
// 虽然主流程已经结束了,但是因为子流程没有join,所以其rootToken仍然停留在fork上
assertEquals("fork", pi.getRootToken().getNode().getName());
// 第二个子流程到达的end和主流程中的end并不是同一个节点
assertTrue(!pi.getRootToken().getNode().equals(stateToken2.getNode()));
}
}
评论
sdliubo
2007-04-26
不错的思路,感谢。。。。
jason2008
2007-02-10
我人生目标是想成为一名架构师,原以为学好struts+hibernate+spring就差不多了,看来我还有很多很多东西要学.
JeffreyHsu
2006-12-05
刚刚看了一下,fork也可以手动signal,流程可以继续
JeffreyHsu
2006-12-05
引用
jeffen2006 17 小时前
我觉得你可以用state来代替join,在state中判断所有要求的子流程是否都完成了,完成了就触发流程继续进行。
我觉得你可以用state来代替join,在state中判断所有要求的子流程是否都完成了,完成了就触发流程继续进行。
这个我思考过,但是即使所有的子流程都结束了,主流程的token仍然停留在fork上,而fork是不能手动signal的,真有点头痛
jeffen2006
2006-12-04
我觉得你可以用state来代替join,在state中判断所有要求的子流程是否都完成了,完成了就触发流程继续进行。
- 浏览: 115719 次
- 性别:

- 来自: 合肥

- 详细资料
搜索本博客
我的相册
grid.png
共 11 张
共 11 张
最近加入圈子
最新评论
-
JavaEE是否适合互联网开发 ...
laiseeme 写道stack3256 写道大量的开源框架和解决方案 一个成熟 ...
-- by liusong1111 -
JavaEE是否适合互联网开发 ...
stack3256 写道大量的开源框架和解决方案 一个成熟的Java程序员和成熟 ...
-- by laiseeme -
JavaEE是否适合互联网开发 ...
校内也是java做的,貌似看见.do的字样。最近也打算写个,但是不想用j2ee了 ...
-- by jkfzero -
JavaEE是否适合互联网开发 ...
大量的开源框架和解决方案 一个成熟的Java程序员和成熟的PHP程序员效率会差多 ...
-- by stack3256 -
JavaEE是否适合互联网开发 ...
互联网应用也看是干啥的吧!几个人就能搞定的小站还用上JAVA这个大炮呀。当然上了 ...
-- by ebeach






评论排行榜