关注JEECG发展历程 关注最新动态和版本, 记录JEECG成长点滴 更新日志 - 技术支持 - 招聘英才

JEECG最新版本下载 JEECG智能开发平台 - 显著提高开发效率 常见问题 - 入门视频 - 参与开源团队

商务QQ: 69893005、418799587 商务热线(5*8小时): 010-64808099 官方邮箱: jeecgos@163.com

查看: 13039|回复: 0

Activiti 5.3:子流程(subProcess)

[复制链接]
发表于 2016-3-4 11:40:17 | 显示全部楼层 |阅读模式

Activiti 5.3提供了子流程的实现,包括两种基于子流程的实现:

一种是内嵌子流程:子流程元素<subProcess>内嵌在主流程元素<process>之内,只能在该流程中使用该子流程,外部是无法访问到的。这种子流程一般作为局部通用逻辑处理,或者因为特定业务需要,使得比较复杂的单个主流程设计清晰直观;

另一种是调用子流程:首先实现一个流程,在另一个流程中可以调用该流程,通常可以定义一些通用的流程作为这种调用子流程,供其他多个流程定义复用。这种子流程使用<callActivity>元素来进行调用,间接地嵌入到主流程中,用起来比较方便。

一、内嵌子流程

实现的基于内嵌子流程的流程,示例如图所示:

1.png

对应的流程定义文件SubProcessTest.MySubprocess.bpmn20.xml,内容如下所示:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <definitions id="definitions"
  3.     xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn"
  4.     targetNamespace="Examples">
  5.     <process id="MySubprocess" name="My Subprocess">
  6.         <startEvent id="theStart" />
  7.         <sequenceFlow id="flow1" sourceRef="theStart" targetRef="subProcess" />
  8.          
  9.         <subProcess id="subProcess">
  10.             <startEvent id="subProcessStart" />
  11.             <sequenceFlow id="flow2" sourceRef="subProcessStart" targetRef="subProcessFork" />
  12.             <parallelGateway id="subProcessFork" />
  13.             <sequenceFlow id="flow3" sourceRef="subProcessFork" targetRef="task1" />
  14.             <sequenceFlow id="flow4" sourceRef="subProcessFork" targetRef="task2" />
  15.             <userTask id="task1" name="Check bank" activiti:candidateGroups="engineering">
  16.                 <extensionElements>
  17.                     <activiti:taskListener event="complete"
  18.                         class="org.shirdrn.workflow.activiti.subprocess.CheckBankTask" />
  19.                 </extensionElements>
  20.             </userTask>
  21.             <sequenceFlow id="flow5" sourceRef="task1" targetRef="subProcessJoin" />
  22.             <userTask id="task2" name="Investigate software" activiti:candidateGroups="engineering" >
  23.                 <extensionElements>
  24.                     <activiti:taskListener event="complete"
  25.                         class="org.shirdrn.workflow.activiti.subprocess.CheckMerchantTask" />
  26.                 </extensionElements>
  27.             </userTask>
  28.             <sequenceFlow id="flow6" sourceRef="task2" targetRef="subProcessJoin" />
  29.             <parallelGateway id="subProcessJoin" />
  30.             <sequenceFlow id="flow7" sourceRef="subProcessJoin" targetRef="subProcessEnd" />
  31.             <endEvent id="subProcessEnd" />
  32.         </subProcess>

  33.         <sequenceFlow id="flow10" sourceRef="subProcess" targetRef="taskAfterSubProcess" />
  34.         <userTask id="taskAfterSubProcess" name="Collect message" activiti:candidateGroups="engineering" >
  35.             <extensionElements>
  36.                     <activiti:taskListener event="complete"
  37.                         class="org.shirdrn.workflow.activiti.subprocess.CollectMessageTask" />
  38.             </extensionElements>
  39.         </userTask>
  40.         <sequenceFlow id="flow11" sourceRef="taskAfterSubProcess" targetRef="theEnd" />
  41.         <endEvent id="theEnd" />
  42.     </process>

  43. </definitions>
复制代码
流程定义中,实现了3个TaskListener,对应的代码分别如下所示:
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.HashMap;
  3. import java.util.logging.Logger;

  4. import org.activiti.engine.delegate.DelegateTask;
  5. import org.activiti.engine.impl.pvm.delegate.TaskListener;

  6. public class CheckBankTask implements TaskListener {

  7.     private final Logger log = Logger.getLogger(CheckBankTask.class.getName());
  8.      
  9.     @SuppressWarnings("unchecked")
  10.     public void notify(DelegateTask delegateTask) {
  11.         log.info("i am CheckBankTask.");
  12.         System.out.println("in : " + delegateTask.getVariables());
  13.         ((HashMap<String, Object>)delegateTask.getVariables().get("in")).put("next", "CheckBankTask");
  14.         ((HashMap<String, Object>)delegateTask.getVariables().get("out")).put("reponse", "subprocess:CheckBankTask->CheckMerchantTask");
  15.     }
  16. }
复制代码
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.HashMap;

  3. public class CheckMerchantTask implements TaskListener {

  4.     private final Logger log = Logger.getLogger(CheckMerchantTask.class.getName());
  5.      
  6.     @SuppressWarnings("unchecked")
  7.     public void notify(DelegateTask delegateTask) {
  8.         log.info("i am CheckMerchantTask.");
  9.         System.out.println("in : " + delegateTask.getVariables());
  10.         ((HashMap<String, Object>)delegateTask.getVariables().get("in")).put("previous", "CheckMerchantTask");
  11.     }
  12. }
复制代码
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.Map;

  3. public class CollectMessageTask implements TaskListener {

  4.     private final Logger log = Logger.getLogger(CollectMessageTask.class.getName());
  5.      
  6.     @SuppressWarnings("unchecked")
  7.     public void notify(DelegateTask delegateTask) {
  8.         log.info("i am CollectMessageTask.");
  9.         System.out.println("out : " + (Map<String, Object>)delegateTask.getVariables().get("out"));
  10.         System.out.println("all : " + delegateTask.getVariables());
  11.     }
  12. }
复制代码



测试用例,代码如下所示:
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.HashMap;
  3. import java.util.List;
  4. import java.util.Map;

  5. import org.activiti.engine.repository.Deployment;
  6. import org.activiti.engine.runtime.ProcessInstance;
  7. import org.activiti.engine.task.Task;
  8. import org.shirdrn.workflow.activiti.AbstractTest;

  9. /**
  10. * <a href="http://my.oschina.net/arthor" class="referer" target="_blank">@author</a> shirdrn
  11. */
  12. public class MySubProcessTest extends AbstractTest {

  13.     @Override
  14.     protected void initialize() throws Exception {
  15.         Deployment deployment = repositoryService
  16.         .createDeployment()
  17.         .addClasspathResource(
  18.                 "diagrams/SubProcessTest.MySubprocess.bpmn20.xml")
  19.         .deploy();  
  20.         deploymentId = deployment.getId();
  21.     }

  22.     @Override
  23.     protected void destroy() throws Exception {
  24.         repositoryService.deleteDeployment(deploymentId, true);
  25.     }
  26.      
  27.     public void testSubProcess() {
  28.         // prepare data packet
  29.         Map<String, Object> variables = new HashMap<String, Object>();
  30.         Map<String, Object> subVariables = new HashMap<String, Object>();
  31.         variables.put("maxTransCount", 1000000);
  32.         variables.put("merchant", new Merchant("ICBC"));
  33.         variables.put("protocol", "UM32");
  34.         variables.put("repository", "10.10.38.99:/home/shirdrn/repository");
  35.         variables.put("in", subVariables);
  36.         variables.put("out", new HashMap<String, Object>());
  37.          
  38.         // start process instance
  39.         ProcessInstance pi = runtimeService.startProcessInstanceByKey("MySubprocess", variables);
  40.          
  41.         // enter subprocess
  42.         List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc().list();
  43.         assertEquals(2, tasks.size());
  44.          
  45.         for(Task task : tasks) {
  46.             taskService.complete(task.getId());
  47.         }
  48.          
  49.         // leave subprocess
  50.         Task collectTask = taskService.createTaskQuery().processInstanceId(pi.getId()).singleResult();
  51.         assertEquals("Collect message", collectTask.getName());
  52.          
  53.         Map<String, Object> taskVariables = new HashMap<String, Object>();
  54.         taskVariables.put("att", "anything you need");
  55.         taskService.setVariable(collectTask.getId(), "oper", "shirdrn");
  56.         taskService.complete(collectTask.getId(), taskVariables);
  57.     }

  58. }
复制代码
运行结果信息,如下所示:
  1. 2011-3-24 17:36:36 org.shirdrn.workflow.activiti.subprocess.CheckBankTask notify
  2. 信息: i am CheckBankTask.
  3. in : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=Merchant[ICBC], maxTransCount=1000000, in={}, out={}}
  4. 2011-3-24 17:36:36 org.shirdrn.workflow.activiti.subprocess.CheckMerchantTask notify
  5. 信息: i am CheckMerchantTask.
  6. in : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=Merchant[ICBC], maxTransCount=1000000, in={next=CheckBankTask}, out={reponse=subprocess:CheckBankTask->CheckMerchantTask}}
  7. 2011-3-24 17:36:36 org.shirdrn.workflow.activiti.subprocess.CollectMessageTask notify
  8. 信息: i am CollectMessageTask.
  9. out : {reponse=subprocess:CheckBankTask->CheckMerchantTask}
  10. all : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=Merchant[ICBC], oper=shirdrn, att=anything you need, maxTransCount=1000000, in={previous=CheckMerchantTask, next=CheckBankTask}, out={reponse=subprocess:CheckBankTask->CheckMerchantTask}}
复制代码


二、调用子流程

实现的子流程,示例如图所示:

2.png

对应的流程定义文件Subprocess.Check.bpmn20.xml,如下所示:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  3.   <process id="CheckSubprocess" name="CheckSubprocess">
  4.     <startEvent id="startevent4" name="Start"></startEvent>
  5.     <serviceTask id="servicetask4" name="Check User" activiti:class="org.shirdrn.workflow.activiti.subprocess.BusinessCheck"></serviceTask>
  6.     <endEvent id="endevent4" name="End"></endEvent>
  7.     <sequenceFlow id="flow7" name="" sourceRef="startevent4" targetRef="servicetask4"></sequenceFlow>
  8.     <sequenceFlow id="flow8" name="" sourceRef="servicetask4" targetRef="endevent4"></sequenceFlow>
  9.   </process>
  10. </definitions>
复制代码
上面的流程定义,和通常定义流程的方式是相同的。流程中,对应的JavaDelegate的实现类,代码如下所示:
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.logging.Logger;

  3. import org.activiti.engine.delegate.DelegateExecution;
  4. import org.activiti.engine.delegate.JavaDelegate;

  5. public class BusinessCheck implements JavaDelegate {
  6.      
  7.     private static final Logger log = Logger.getLogger(BusinessCheck.class.getName());
  8.      
  9.     @Override
  10.     public void execute(DelegateExecution execution) throws Exception {
  11.         // varOutFromMainprocess<->varInSubprocess
  12.         String varInSubprocess = (String)execution.getVariable("varInSubprocess");
  13.         log.info("in subprocess get(varInSubprocess): " + varInSubprocess);
  14.          
  15.         log.info("variavles=" + execution.getVariables());
  16.         execution.setVariable("s:bc", "Subprocess:BusinessCheck");
  17.         log.info("I am BusinessCheck in subprocess.");  
  18.          
  19.         execution.setVariable("varInSubprocess", "BBBB");
  20.         log.info("in subprocess set(varInSubprocess): " + varInSubprocess);
  21.     }
复制代码

该BusinessCheck类简单用来校验用户数据。

下面看一下主流程,如图所示:

3.png

上面的callSubprocess结点对应的就是流程定义中的<callActivity>元素,调用了外部流程。对应的流程定义文件Subprocess.Mainprocess.bpmn20.xml,如下所示:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
  4.     xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
  5.     xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
  6.     expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  7.     <process id="Mainprocess" name="Main Process">
  8.         <startEvent id="startevent1" name="Start"></startEvent>
  9.         <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="servicetask1"></sequenceFlow>
  10.         <serviceTask id="servicetask1" name="System Initialization" activiti:class="org.shirdrn.workflow.activiti.subprocess.Initialization"></serviceTask>
  11.         <sequenceFlow id="flow2" name="" sourceRef="servicetask1" targetRef="callSubprocess"></sequenceFlow>
  12.         <callActivity id="callSubprocess" calledElement="CheckSubprocess" >
  13.           <extensionElements>
  14.                   <activiti:in source="varOutFromMainprocess" target="varInSubprocess" />
  15.                   <activiti:out source="varInSubprocess" target="varOutFromSubprocess" />
  16.           </extensionElements>
  17.         </callActivity>
  18.         <sequenceFlow id="flow3" name="" sourceRef="callSubprocess" targetRef="servicetask2"></sequenceFlow>
  19.         <serviceTask id="servicetask2" name="Do Transaction" activiti:class="org.shirdrn.workflow.activiti.subprocess.DoTransaction"></serviceTask>
  20.         <sequenceFlow id="flow4" name="" sourceRef="servicetask2" targetRef="endevent1"></sequenceFlow>
  21.         <endEvent id="endevent1" name="End"></endEvent>
  22.     </process>
  23. </definitions>
复制代码
需要说明的是,对于主流程与子流程之间进行数据交换,需要在<callActivity>元素中进行配置,通过执行“传入”、“传出”变量的方式来进行。片段如下所示:
  1. <callActivity id="callSubprocess" calledElement="CheckSubprocess" >
  2.   <extensionElements>
  3.       <activiti:in source="varOutFromMainprocess" target="varInSubprocess" />
  4.       <activiti:out source="varInSubprocess" target="varOutFromSubprocess" />
  5.   </extensionElements>
  6. </callActivity>
复制代码
我们可以通过在主流程中设置一个变量为varOutFromMainprocess,并指定对应的输入数据,根据流程定义,会将变量 varOutFromMainprocess对应的值,传递给子流程中的变量varInSubprocess,只需要在子流程中获取变量 varInSubprocess的值即可。从子流程中传出数据的道理是类似的。上面实现了2个JavaDelegate处理类,代码分别如下所示:
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.logging.Logger;

  3. public class Initialization implements JavaDelegate {
  4.      
  5.     private static final Logger log = Logger.getLogger(Initialization.class.getName());
  6.      
  7.     @Override
  8.     public void execute(DelegateExecution execution) throws Exception {
  9.         log.info("variavles=" + execution.getVariables());
  10.         execution.setVariable("m:i", "Mainprocess:Initialization");
  11.         log.info("I am Initialization in mainprocess.");
  12.          
  13.         execution.setVariable("varOutFromMainprocess", "AAAA");
  14.         log.info("in mainprocess set(varOutFromMainprocess): " + execution.getVariable("varOutFromMainprocess"));
  15.     }
  16. }
复制代码
  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.logging.Logger;

  3. public class DoTransaction implements JavaDelegate {
  4.      
  5.     private static final Logger log = Logger.getLogger(DoTransaction.class.getName());
  6.      
  7.     @Override
  8.     public void execute(DelegateExecution execution) throws Exception {
  9.         // varInSubprocess<->varOutFromSubprocess
  10.         String varOutFromSubprocess = (String)execution.getVariable("varOutFromSubprocess");
  11.         log.info("in mainprocess get(varOutFromSubprocess): " + varOutFromSubprocess);
  12.          
  13.         log.info("variavles=" + execution.getVariables());
  14.         execution.setVariable("m:dt", "Mainprocess:DoTransaction");
  15.         log.info("I am DoTransaction in mainprocess.");
  16.     }
  17. }
复制代码



实现的测试用例,代码如下所示:

  1. package org.shirdrn.workflow.activiti.subprocess;

  2. import java.util.HashMap;
  3. import java.util.Map;

  4. import org.activiti.engine.repository.Deployment;
  5. import org.activiti.engine.runtime.ProcessInstance;
  6. import org.shirdrn.workflow.activiti.AbstractTest;

  7. /**
  8. * <a href="http://my.oschina.net/arthor" class="referer" target="_blank">@author</a> shirdrn
  9. */
  10. public class MainprocessTest extends AbstractTest {

  11.     @Override
  12.     protected void initialize() throws Exception {
  13.         Deployment deployment = repositoryService
  14.         .createDeployment()
  15.         .addClasspathResource(
  16.                 "diagrams/Subprocess.Check.bpmn20.xml")
  17.         .deploy();  
  18.         deploymentIdList.add(deployment.getId());
  19.          
  20.         deployment = repositoryService
  21.         .createDeployment()
  22.         .addClasspathResource(
  23.                 "diagrams/Subprocess.Mainprocess.bpmn20.xml")
  24.         .deploy();  
  25.         deploymentIdList.add(deployment.getId());
  26.     }

  27.     @Override
  28.     protected void destroy() throws Exception {
  29.         for(String deployment : deploymentIdList) {
  30.             repositoryService.deleteDeployment(deployment, true);   
  31.         }
  32.     }
  33.      
  34.     public void testSubProcess() {
  35.         // prepare data packet
  36.         Map<String, Object> variables = new HashMap<String, Object>();
  37.         Map<String, Object> subVariables = new HashMap<String, Object>();
  38.         variables.put("protocol", "UM32");
  39.         variables.put("repository", "10.10.38.99:/home/shirdrn/repository");
  40.         variables.put("in", subVariables);
  41.         variables.put("out", new HashMap<String, Object>());
  42.          
  43.         // start process instance
  44.         ProcessInstance pi = runtimeService.startProcessInstanceByKey("Mainprocess", variables);
  45.          
  46.         assertEquals(true, pi.isEnded());
  47.     }

  48. }
复制代码
代码中org.shirdrn.workflow.activiti.AbstractTest类可以参考: Activiti 5.3:流程活动自动与手工触发执行里面。上述测试程序运行结果如下所示:[size=1em]
  1. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.Initialization execute
  2. 信息: variavles={protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, in={}, out={}}
  3. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.Initialization execute
  4. 信息: I am Initialization in mainprocess.
  5. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.Initialization execute
  6. 信息: in mainprocess set(varOutFromMainprocess): AAAA
  7. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.BusinessCheck execute
  8. 信息: in subprocess get(varInSubprocess): AAAA
  9. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.BusinessCheck execute
  10. 信息: variavles={varInSubprocess=AAAA}
  11. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.BusinessCheck execute
  12. 信息: I am BusinessCheck in subprocess.
  13. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.BusinessCheck execute
  14. 信息: in subprocess set(varInSubprocess): AAAA
  15. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.DoTransaction execute
  16. 信息: in mainprocess get(varOutFromSubprocess): BBBB
  17. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.DoTransaction execute
  18. 信息: variavles={protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, varOutFromSubprocess=BBBB, varOutFromMainprocess=AAAA, in={}, out={}, m:i=Mainprocess:Initialization}
  19. 2011-3-24 17:52:13 org.shirdrn.workflow.activiti.subprocess.DoTransaction execute
  20. 信息: I am DoTransaction in mainprocess.
复制代码


相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表