`
longgangbai
  • 浏览: 7238534 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

工作流Activiti的学习总结(九)Activiti手工执行的应用(ReceiveTask实现方式)

 
阅读更多

 工作流模拟的业务情景如下:
           1.用户到银行转账业务
           2.银行工作人员查询用户余额
           3.银行工作人员帮助用户转账

 手工触发执行是指,执行到流程中某个个结点后流程暂时停止运行,直到收到外部发送的信号
  以后,才会继续向前推进,这样情况可以更加精细地控制流程。 

针对用户手动执行的任务可以采用手工触发执行 
       通过<receiveTask>和<userTask>元素都可以实现流程的手工触发执行。

 

本文讲解ReceiveTask方式实现:

配置如下:

 

   <receiveTask id="receivetask2" name="开始转账">
      <extensionElements>
         <activiti:executionListener event="start" class="com.easyway.workflow.activiti.CheckMerchantMoneyTask"></activiti:executionListener>
      </extensionElements>
    </receiveTask>

 

 

流程图如下:

 

流程配置如下:

 

<?xml version="1.0" encoding="UTF-8"?>
<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">
  <process id="BankUserTask" name="BankUserTask">
    <documentation>Place documentation for the 'BankUserTask' process here.</documentation>
    <startEvent id="startevent1" name="准备转账业务"></startEvent>
    <endEvent id="endevent1" name="转账结束"></endEvent>
    <receiveTask id="receivetask1" name="检查账户余额">
     <extensionElements>
        <activiti:executionListener event="start" class="com.easyway.workflow.activiti.CheckBankAccountMoneyTask"/>
     </extensionElements>
    </receiveTask>
    <receiveTask id="receivetask2" name="开始转账">
      <extensionElements>
         <activiti:executionListener event="start" class="com.easyway.workflow.activiti.CheckMerchantMoneyTask"></activiti:executionListener>
      </extensionElements>
    </receiveTask>
    <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="receivetask1"></sequenceFlow>
    <sequenceFlow id="flow2" name="" sourceRef="receivetask1" targetRef="receivetask2"></sequenceFlow>
    <sequenceFlow id="flow3" name="" sourceRef="receivetask2" targetRef="endevent1"></sequenceFlow>
    <sequenceFlow id="flow4" name="" sourceRef="receivetask1" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_BankUserTask">
    <bpmndi:BPMNPlane bpmnElement="BankUserTask" id="BPMNPlane_BankUserTask">
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35" width="35" x="76" y="218"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35" width="35" x="590" y="220"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="receivetask1" id="BPMNShape_receivetask1">
        <omgdc:Bounds height="55" width="105" x="160" y="210"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="receivetask2" id="BPMNShape_receivetask2">
        <omgdc:Bounds height="55" width="105" x="340" y="210"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="111" y="235"></omgdi:waypoint>
        <omgdi:waypoint x="160" y="237"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="265" y="237"></omgdi:waypoint>
        <omgdi:waypoint x="340" y="237"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="445" y="237"></omgdi:waypoint>
        <omgdi:waypoint x="590" y="237"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
        <omgdi:waypoint x="265" y="237"></omgdi:waypoint>
        <omgdi:waypoint x="212" y="338"></omgdi:waypoint>
        <omgdi:waypoint x="385" y="338"></omgdi:waypoint>
        <omgdi:waypoint x="607" y="338"></omgdi:waypoint>
        <omgdi:waypoint x="607" y="255"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

 

 

代码实现如下:

 

 

/**
package com.easyway.workflow.activiti;
import java.util.HashMap;
/**
 * 银行工作人员开始查询用户余额的事件
 * 
 * @author longgangbai
 * 
 * 2011-12-17  上午09:37:50
 */
public class CheckBankAccountMoneyTask implements JavaDelegate {

	private final Logger log = Logger.getLogger(CheckBankAccountMoneyTask.class.getName());

	@SuppressWarnings("unchecked")
	@Override
	public void execute(DelegateExecution execution) throws Exception {
		log.info("根据输入参数,开始检查银行账户余额........");
		System.out.println("in : " + execution.getVariables());
		((HashMap<String, Object>)execution.getVariables().get("in")).put("next", "CheckBankTask");
		((HashMap<String, Object>)execution.getVariables().get("out")).put("reponse", "subprocess:CheckBankReceiveTask->CheckMerchantReceiveTask");		
	}
}

 

 

package com.easyway.workflow.activiti;

import java.util.HashMap;
/**
 * 
 * 银行工作人员开始转账过程
 * @author longgangbai
 * 
 * 2011-12-17  下午09:39:14
 */
public class CheckMerchantMoneyTask implements JavaDelegate {

	private final Logger log = Logger.getLogger(CheckMerchantMoneyTask.class.getName());
	
	@SuppressWarnings("unchecked")
	@Override
	public void execute(DelegateExecution execution) throws Exception {
		log.info("正在转账中.........");
		System.out.println("in : " + execution.getVariables());
		((HashMap<String, Object>)execution.getVariables().get("in")).put("previous", "CheckMerchantReceiveTask");
	}
}

 

 

package com.easyway.workflow.activiti;


import junit.framework.TestCase;
/**
 * 主要是在测试之前做一些初始化工作,主要包括流程引擎实例
 * 的构建,及其流程提供的基本服务。
 * 目的:让开发者熟悉工作流使用过程使用的几个步骤
 * 1.加载相关的工作流全局配置文件activiti.cfg.xml配置文件信息
 * 2.获取工作流相关的服务(RepositoryService,RuntimeService,
 *    TaskService,HistoryService,FormService,ManagementService,
 *    IdentityService等)
 * 2.加载工作流文件*.bpmn20.xml信息
 * 
 * 3.部署工作流
 *    部署工作流由多种方式,在以后会相继讲解
 * 
 * @author longgangbai
 * 
 * 2011-12-17  下午07:48:59
 */
public abstract class AbstractTest extends TestCase {

	private ProcessEngine processEngine;
	protected String deploymentId;
	protected RepositoryService repositoryService;
	protected RuntimeService runtimeService;
	protected TaskService taskService;
	protected FormService formService;
	protected HistoryService historyService;
	protected IdentityService identityService;
	protected ManagementService managementService;
	
	
	/**
	 * 测试用例开始初始化工作
	 * 1.创建相关的工作流程对象ProcessEngine
	 * 2.创建相关的服务
	 * 3.
	 */
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		//由于ProcessEngine为线程安全性对象,整个项目可以共用一个
		if(processEngine==null) {
			//此处使用此种方法调用的activiti的配置文件为 classpath路径下的activiti.cfg.xml
			//采用的H2的数据库
			processEngine = ProcessEngines.getDefaultProcessEngine();
		}
		//获取工作流的各种服务信息
		repositoryService = processEngine.getRepositoryService();
		runtimeService = processEngine.getRuntimeService();
		taskService = processEngine.getTaskService();
		formService = processEngine.getFormService();
		historyService = processEngine.getHistoryService();
		identityService = processEngine.getIdentityService();
		managementService = processEngine.getManagementService();
		//调用扩展的初始化工作
		initialize();
		
	}
	
	/**
	 * test销毁方法
	 */
	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		destroy();
	}
	
	/**
	 * 便于子类的工作的初始化的扩展工作
	 * 
	 * 
	 * @throws Exception
	 */
	protected abstract void initialize() throws Exception;
	/**
	 * 便于子类的工作的销毁的扩展工作
	 * 
	 * @throws Exception
	 */
	protected abstract void destroy() throws Exception;
}

 

 

/**
package com.easyway.workflow.activiti;



import java.util.HashMap;
/**
 * 
 * 自定义测试的工作流的方式
 * 
 * @author longgangbai
 * 
 * 2011-12-17  下午10:12:54
 */
public class CustomBankAccountMoneyTaskJunit3Test  extends AbstractTest {

	/**
	 * 初始化工作流程的方法
	 */
	@Override
	protected void initialize() throws Exception {
		Deployment deployment = repositoryService
		.createDeployment()
		.addClasspathResource(
				"com/easyway/workflow/activiti/BankUserTaskActiviti.bpmn20.xml")
	.deploy();	
		deploymentId = deployment.getId();
	}
	
	/**
	 * 销毁工作流对象的方法
	 */
	@Override
	protected void destroy() throws Exception {
		repositoryService.deleteDeployment(deploymentId, true);	
	}
	
	/**
	 * 测试工作流流程的方法
	 */
	public void testSubProcess() {
		// prepare data packet
		Map<String, Object> variables = new HashMap<String, Object>();
		Map<String, Object> subVariables = new HashMap<String, Object>();
		variables.put("maxTransCount", 1000000);
		variables.put("merchant", "ICBC");
		variables.put("protocol", "UM32");
		variables.put("repository", "10.10.38.99:/home/shirdrn/repository");
		variables.put("in", subVariables);
		variables.put("out", new HashMap<String, Object>());
		
		// start process instance
		//将初始化时候创建流程时设置参数
		ProcessInstance pi = runtimeService.startProcessInstanceByKey("BankUserTask", variables);
		List<Execution> executions = runtimeService.createExecutionQuery().list();
		assertEquals(1, executions.size());
		
		Execution execution = runtimeService.createExecutionQuery().singleResult();
		runtimeService.setVariable(execution.getId(), "type", "receiveTask");
		//同意执行信息发送信号
		runtimeService.signal(execution.getId());
		assertEquals(1, executions.size());
		
		execution = runtimeService.createExecutionQuery().list().get(0);
		assertNotNull(execution);
		//设置工作流实例对应的变量
		runtimeService.setVariable(execution.getId(), "oper", "shirdrn");
			runtimeService.signal(execution.getId());
		}
}

 

采用官方推荐Junit3实现测试如下:

/**
package com.easyway.workflow.activiti;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.ActivitiTestCase;
import org.activiti.engine.test.Deployment;
/**
 * 手工触发执行是指,执行到流程中某个个结点后流程暂时停止运行,直到收到外部发送的信号
 * 以后,才会继续向前推进,这样情况可以更加精细地控制流程。 
 * 手工触发执行 
 * 通过<receiveTask>和<userTask>元素都可以实现流程的手工触发执行。 
 * 
 * 
 * 版本单元测试采用官方推荐的Junit3方式测试Activiti工作流
 *  ,必须实现继承自ActivtiTestCase类实现的,默认activiti全局配置文件采用.
 *  activiti.cfg.xml并且测试的工作流文件的名称是测试类的名称,
 *  ActivitiTestCase 的 protected void setUp()方法调用如下
 *   deploymentId = TestHelper.annotationDeploymentSetUp(processEngine, getClass(), getName());
 *  
 *  TestHelper类调用说明如下:
 *  
*    * get a resource location by convention based on a class (type) and a
*    * relative resource name. The return value will be the full classpath
*    * location of the type, plus a suffix built from the name parameter:
*    * <code>.&lt;name&gt;.bpmn20.xml</code>.
*    public static String getBpmnProcessDefinitionResource(Class< ? > type, String name) {
*     return type.getName().replace('.', '/') + "." + name + "." + BpmnDeployer.BPMN_RESOURCE_SUFFIX;
*   }
*   
 * @author longgangbai
 * 
 * 2011-12-17  下午09:51:13
 */
public class CheckBankAccountMoneyTaskJunit3Test extends ActivitiTestCase {
	 
	    /**
	     * 採用Junit3方式测试工作流中的方法
	     */
	    @Deployment(resources="com/easyway/workflow/activiti/BankUserTaskActiviti.bpmn20.xml")
		public void testSubProcess() {
			// prepare data packet
	    	//设置开始执行的工作流的初始化参数
			Map<String, Object> variables = new HashMap<String, Object>();
			Map<String, Object> subVariables = new HashMap<String, Object>();
			variables.put("maxTransCount", 1000000);
			variables.put("merchant", "ICBC");
			variables.put("protocol", "UM32");
			variables.put("repository", "10.10.38.99:/home/shirdrn/repository");
			variables.put("in", subVariables);
			variables.put("out", new HashMap<String, Object>());
			// start process instance
			//根据工作流ID获取工作流引擎实例
			ProcessInstance pi = runtimeService.startProcessInstanceByKey("BankUserTask", variables);
			deploymentId=pi.getProcessDefinitionId();
			System.out.println("deploymentId="+deploymentId);
            //获取中的实例数
			List<Execution> executions = runtimeService.createExecutionQuery().list();
			assertEquals(1, executions.size());
			
			//查询单个实例
			Execution execution = runtimeService.createExecutionQuery().singleResult();
			//设置运行时服务变量
			runtimeService.setVariable(execution.getId(), "type", "receiveTask");
		    //向特定的流程实例发送触发器执行的信号
			runtimeService.signal(execution.getId());
			assertEquals(1, executions.size());
			
			execution = runtimeService.createExecutionQuery().list().get(0);
			assertNotNull(execution);
			runtimeService.setVariable(execution.getId(), "oper", "shirdrn");
			runtimeService.signal(execution.getId());
		}
	}

 

采用官方推荐Junit4实现测试如下:

/**
package com.easyway.workflow.activiti;

import static org.junit.Assert.assertEquals;

/**
 * 
 * 
 * 工作流模拟的业务情景如下:
 *  1.用户到银行转账业务
 *  2.银行工作人员查询用户余额
 *  3.银行工作人员帮助用户转账
 *  
 * 在工作流activiti中使用Junit4测试需要使用ActivitiRule对象,创建各种对象。
 * 
 * @author longgangbai
 * 
 * 2011-12-17  下午11:17:35
 */
public class CheckBankAccountMoneyTaskJunit4Test {
	  @Rule 
	  public ActivitiRule activitiRule = new ActivitiRule(); 
	   
	  @Test 
	  @Deployment(resources="com/easyway/workflow/activiti/BankUserTaskActiviti.bpmn20.xml")
	  public void ruleUsageExample() { 
			//设置开始执行的工作流的初始化参数
			Map<String, Object> variables = new HashMap<String, Object>();
			Map<String, Object> subVariables = new HashMap<String, Object>();
			variables.put("maxTransCount", 1000000);
			variables.put("merchant", "ICBC");
			variables.put("protocol", "UM32");
			variables.put("repository", "10.10.38.99:/home/shirdrn/repository");
			variables.put("in", subVariables);
			variables.put("out", new HashMap<String, Object>());
			// start process instance
			//根据工作流ID获取工作流引擎实例
			RuntimeService runtimeService = activitiRule.getRuntimeService(); 
			ProcessInstance pi = runtimeService.startProcessInstanceByKey("BankUserTask", variables);
			String deploymentId=pi.getProcessDefinitionId();
			System.out.println("deploymentId="+deploymentId);
		    //获取中的实例数
			List<Execution> executions = runtimeService.createExecutionQuery().list();
			assertEquals(1, executions.size());
			
			//查询单个实例
			Execution execution = runtimeService.createExecutionQuery().singleResult();
			//设置运行时服务变量
			runtimeService.setVariable(execution.getId(), "type", "receiveTask");
		    //向特定的流程实例发送触发器执行的信号
			runtimeService.signal(execution.getId());
			assertEquals(1, executions.size());
			
			execution = runtimeService.createExecutionQuery().list().get(0);
			assertNotNull(execution);
			runtimeService.setVariable(execution.getId(), "oper", "shirdrn");
			runtimeService.signal(execution.getId());
	  } 
	} 

 

 运行结果如下:

2011-12-18 13:08:45 org.activiti.engine.impl.ProcessEngineImpl <init>
信息: ProcessEngine default created
2011-12-18 13:08:45 org.activiti.engine.impl.jobexecutor.JobAcquisitionThread run
信息: JobAcquisitionThread starting to acquire jobs
2011-12-18 13:08:45 org.activiti.engine.impl.bpmn.deployer.BpmnDeployer deploy
信息: Processing resource com/easyway/workflow/activiti/BankUserTaskActiviti.bpmn20.xml
2011-12-18 13:08:45 org.activiti.engine.impl.bpmn.parser.BpmnParse parseDefinitionsAttributes
信息: XMLSchema currently not supported as typeLanguage
2011-12-18 13:08:45 org.activiti.engine.impl.bpmn.parser.BpmnParse parseDefinitionsAttributes
信息: XPath currently not supported as expressionLanguage
2011-12-18 13:08:46 com.easyway.workflow.activiti.CheckBankAccountMoneyTask execute
信息: 根据输入参数,开始检查银行账户余额........
in : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=ICBC, maxTransCount=1000000, in={}, out={}}
deploymentId=BankUserTask:1:1313
2011-12-18 13:08:46 com.easyway.workflow.activiti.CheckMerchantMoneyTask execute
信息: 正在转账中.........
in : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=ICBC, maxTransCount=1000000, type=receiveTask, in={}, out={}}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics