零全零美(www.zzgwt.com)
生活中的很多事情,并不像If...Else那么简单!
posts - 96,comments - 52,trackbacks - 0
         关于JBPM中并发子流程的实现方式,网上有很多的说法,但是好像每种办法都有这样那样的缺点,要么实现太复杂,要么就是会使Token无法继续流转。这里我介绍一种我的并发子流程的实现方式:使用TaskNode使任务并行的方式,模拟实现JBPM子流程的并发执行。
 我先简单的介绍一下实现思路:
         1、数据库中应该有至少三个已经发布过的流程定义(ProcessDefinition),发布的顺序无所谓,一个主流程两个子流程
         2、我们在主流程中要实现并发子流程的环节放置TaskNode,设置create-tasks="false"、signal="last-wait"
         3、我们想要实现几个子流程的并发就在第二步放置的TaskNode中放置几个Task,每个Task的名字都是要并发的子流程的名称
         4、在TaskNode的Node-Enter action中,我们手动为每一个Task创建一个任务实例,同时我们取得Task的名字也就是要并发的子流程的名字,创建流程实例
         5、为每个新创建的流程实例设置流程变量:TaskInstanceID表示创建当前子流程的那个主流程任务实例ID,并使子流程开始流转
         6、子流程结束,取得流程变量TaskInstanceID,该流程变量TaskInstanceID是创建他的那个主流程的任务实例,得到该TaskInstance,并TaskInstance.end();
         这个时候因为我们设置了TaskNode的Signal为"last-wait",所以当所有的子流程均结束的时候,主流程才会继续,这样我们也就实现了子流程的并发效果。很简单的一个思路实现起来也并不复杂. 
    
    首先让我们看一下主流程的流程定义:
 1<?xml version="1.0" encoding="UTF-8"?>
 2<process-definition  xmlns=""  name="super1">
 3    <start-state name="start-state1">
 4        <transition to="task-node1"></transition>
 5    </start-state>
 6
 7    <task-node name="task-node1" create-tasks="false" signal="last-wait">
 8        <description>
 9            我们要利用这个TaskNode实现并发子流程,create-tasks="true"是为了可以手动控制任务实例的创建,同时创建子流程,
10            signal="last-wait"是为了实现当所有子流程均已完成,主流程才能继续运行的效果
11        </description>
12        <task name="sub1">
13            <description>要并发的子流程之一</description>
14        </task>
15        <task name="sub2">
16            <description>要并发的子流程之二</description>
17        </task>
18        <event type="node-enter">
19            <action name="NodeEnterAction" class="jbpmTest.bfzlc.action.NodeEnterAction"></action>
20        </event>
21        <transition to="end-state1"></transition>
22    </task-node>
23
24    <end-state name="end-state1"></end-state>
25
26    <event type="process-start">
27        <script name="SuperProcessStart">
28            System.out.println(&quot;主流程启动,并设置主流程ID&quot;);
29        </script>
30    </event>
31    <event type="process-end">
32        <script name="SuperProcessEnd">
33            System.out.println(&quot;主流程结束&quot;);
34        </script>
35    </event>
36</process-definition>

    下面是主流程的Node-EnterAction的代码:

 1public class NodeEnterAction implements ActionHandler {
 2
 3    public void execute(ExecutionContext executionContext) throws Exception {
 4        //取得本节点所有的Task
 5        Set<Task> tasks = ((TaskNode)executionContext.getNode()).getTasks();
 6        
 7        TaskMgmtInstance tgmt = executionContext.getTaskMgmtInstance();
 8        
 9        for (Task task : tasks) {
10            //为每一个Task创建实例
11            TaskInstance taskInstance = tgmt.createTaskInstance(task, executionContext);
12            //业务Service
13            JbpmTestFacade jbpmTestFacade = ((JbpmTestFacade)SpringBeanUtil.getBean("jbpmTestFacade"));
14            //根据Task的名字,为每一个Task创建相应的子流程
15            ProcessInstance processInstance = jbpmTestFacade.createProcessInstance(task.getName());
16            //设置创建这个子流程的流程实例ID
17            processInstance.getContextInstance().setVariable("TaskInstanceID", taskInstance.getId());
18            //子流程开始流转
19            processInstance.signal();
20        }

21        
22    }

23}

        再看其中一个子流程的定义:

 1<?xml version="1.0" encoding="UTF-8"?>
 2<process-definition  xmlns=""  name="sub1">
 3    <start-state name="start-state1">
 4        <transition to="Sub1Task"></transition>
 5    </start-state>
 6
 7    <task-node name="Sub1Task">
 8        <task name="SubTask1"></task>
 9        <transition to="end-state1"></transition>
10    </task-node>
11
12    <end-state name="end-state1"></end-state>
13
14    <event type="process-start">
15        <script name="ProcessStartScript">
16            System.out.println(&quot;-------------------sub1流程启动------------------------------&quot;);
17        </script>
18    </event>
19
20    <event type="process-end">
21        <action name="SubProcessEndAction" class="jbpmTest.bfzlc.action.SubProcessEndAction"></action>
22    </event>
23</process-definition>
24

        下面是该子流程的ProcessEndAction:

 1public class SubProcessEndAction implements ActionHandler {
 2
 3    public void execute(ExecutionContext executionContext) throws Exception {
 4        System.out.println(executionContext.getProcessDefinition().getName()+"结束");
 5        //得到创建当前子流程的那个TaskInstanceID
 6        String taskInstanceID = executionContext.getContextInstance().getVariable("TaskInstanceID").toString();
 7        
 8        //业务Service
 9        JbpmTestFacade jbpmTestFacade = ((JbpmTestFacade)SpringBeanUtil.getBean("jbpmTestFacade"));
10        //取得创建当前子流程的那个主流程taskInstance
11        TaskInstance taskInstance = jbpmTestFacade.geTaskInstance(Long.valueOf(taskInstanceID));
12        taskInstance.end();
13    }

14
15}
   
     思路很清楚,代码也很简单,按照这种方式我们可以让子流程实现所有Task能实现的功能。

    文章原创,转载请注明出处!
posted on 2008-11-12 15:00 零全零美 阅读(3303) 评论(6)  编辑  收藏 所属分类: jbpm

FeedBack:
# re: [原创]JBPM实践之:并发子流程的实现
2008-11-25 16:30 | zhaoyta
有问题  回复  更多评论
  
# re: [原创]JBPM实践之:并发子流程的实现
2008-11-25 16:31 | zhaoyta
假如你主流程里的task是分配给一个人,子流程也有可能建立其他任务给这个人。
这个时候这个人获得了多个任务,如果手动把主流程的task结束了怎么办

  回复  更多评论
  
# re: [原创]JBPM实践之:并发子流程的实现
2008-11-25 17:39 | 昨夜流星
@zhaoyta
看来你还是没有明白我文中所说的思路啊,主流程中用于创建子流程的那个Task是不分配给任何人的,该任务的实例从Task-Node的Enter-action中被创建,然后会把taskInstanceID作为流程级变量放入该任务实例创建的子流程中,在该子流程的Process-end的action中从流程变量里取出该taskInstanceId,然后把该任务实例结束掉。  回复  更多评论
  
# re: [原创]JBPM实践之:并发子流程的实现
2009-05-03 09:53 | zhengjj
要是实现数量不定的并发子流程,需要如何实现?请给点提示  回复  更多评论
  
# re: [原创]JBPM实践之:并发子流程的实现
2009-05-19 10:13 | shappy
@zhengjj
苯啊,通过流程变量或者其他变通的方式传递你需要建立的子流程数,甚至不通过任务名来建立自流程,自己传变量确定子流程的名称和数量也可以嘛。楼主起了个思路,其他的就很好做了。  回复  更多评论
  
# re: [原创]JBPM实践之:并发子流程的实现
2009-05-31 22:27 | 昨夜流星
楼上正解,其实我也是提供了一个基本的思路而已!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: