工作流activiti自动执行任务的开发应用
工作流模拟某公司请假流程情景如下:
1.开发人员请假流程,如果开发人员请假,如果请假天数小于3天,组长批准,人事批准即可请假。
2.如果请假大约三天,需要项目经理或者产品经理批准,并且项目总监批准
模拟自动审批:
只需要启动一个流程实例,它会自动执行到结束。这种情况下,你不需要关注流
程的执行进度,而只需要把精力集中在每个结点的处理逻辑(通常是简单或者复杂的商业逻辑)上。
流程设计图如下:
流程配置文件AutoExecuteTask.bpmn20.xml如下:
<?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="AutoExecuteTask" name="AutoExecuteTask"> <startEvent id="startevent1" name="Start"></startEvent> <parallelGateway id="parallelgateway1" name="多种请假方式"></parallelGateway> <serviceTask id="servicetask1" name="项目经理同意" activiti:class="com.easyway.workflow.activiti.gateway.DeveloperManagerServiceTask"></serviceTask> <serviceTask id="servicetask2" name="产品经理同意" activiti:class="com.easyway.workflow.activiti.gateway.ProductManagerServiceTask"></serviceTask> <serviceTask id="servicetask3" name="项目组长同意" activiti:class="com.easyway.workflow.activiti.gateway.TeamLeaderServiceTask"></serviceTask> <parallelGateway id="parallelgateway2" name="First Join"></parallelGateway> <serviceTask id="servicetask4" name="项目总监同意" activiti:class="com.easyway.workflow.activiti.gateway.ProductBossServiceTask"></serviceTask> <parallelGateway id="parallelgateway3" name="人事判断"></parallelGateway> <serviceTask id="servicetask5" name="人事部门同意" activiti:class="com.easyway.workflow.activiti.gateway.HumanResouceServiceTask"></serviceTask> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="parallelgateway1"></sequenceFlow> <sequenceFlow id="flow2" name="" sourceRef="parallelgateway1" targetRef="servicetask1"></sequenceFlow> <sequenceFlow id="flow3" name="" sourceRef="parallelgateway1" targetRef="servicetask2"></sequenceFlow> <sequenceFlow id="flow4" name="" sourceRef="parallelgateway1" targetRef="servicetask3"></sequenceFlow> <sequenceFlow id="flow5" name="" sourceRef="servicetask1" targetRef="parallelgateway2"></sequenceFlow> <sequenceFlow id="flow6" name="" sourceRef="servicetask2" targetRef="parallelgateway2"></sequenceFlow> <sequenceFlow id="flow7" name="" sourceRef="servicetask3" targetRef="parallelgateway3"></sequenceFlow> <sequenceFlow id="flow8" name="" sourceRef="parallelgateway2" targetRef="servicetask4"></sequenceFlow> <sequenceFlow id="flow9" name="" sourceRef="servicetask4" targetRef="parallelgateway3"></sequenceFlow> <sequenceFlow id="flow10" name="" sourceRef="parallelgateway3" targetRef="servicetask5"></sequenceFlow> <sequenceFlow id="flow11" name="" sourceRef="servicetask5" targetRef="endevent1"></sequenceFlow> </process> </definitions>
package com.easyway.workflow.activiti.gateway;
import java.util.logging.Logger;
/**
* execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
*通过基于Activiti 5.6的<parallelGateway>、<serviceTask>、<receiveTask>、<userTask>元素。
*
*自动执行
<serviceTask>元素,可以实现自动活动,语法如下所示:
<serviceTask id="serviceTaskId" name="serviceTaskName"
activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTaskClass"/>
其中,activiti:class属性为该结点对应的处理类,该类要求实现org.activiti.engine.delegate.JavaDelegate接口
*
* <serviceTask id="servicetask1" name="项目经理同意" activiti:class="com.easyway.workflow.activiti.gateway.DeveloperManagerServiceTask"></serviceTask>
* 项目经理审批过程
* @author longgangbai
*
*
* 2011-12-17 下午07:45:47
*/
public class DeveloperManagerServiceTask implements JavaDelegate {
private final Logger log = Logger.getLogger(DeveloperManagerServiceTask.class.getName());
@Override
public void execute(DelegateExecution execution) throws Exception {
Thread.sleep(10000);
log.info("variavles=" + execution.getVariables());
execution.setVariable("项目经理", "请假天数大约3天,同意请假。");
log.info("项目经理,请假天数大约3天,同意请假。.");
}
}
package com.easyway.workflow.activiti.gateway;
import java.util.logging.Logger;
/**
* execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
*
*
* <serviceTask id="servicetask2" name="产品经理同意" activiti:class="com.easyway.workflow.activiti.gateway.ProductManagerServiceTask"></serviceTask>
* 产品经理审批过程
* @author longgangbai
*
* 2011-12-17 下午07:45:47
*/
public class ProductManagerServiceTask implements JavaDelegate {
private final Logger log = Logger.getLogger(ProductManagerServiceTask.class.getName());
@Override
public void execute(DelegateExecution execution) throws Exception {
Thread.sleep(10000);
log.info("variavles=" + execution.getVariables());
execution.setVariable("产品经理", "请假天数大约3天,同意请假。");
log.info("产品经理,请假天数大约3天,同意请假。");
}
}
package com.easyway.workflow.activiti.gateway;
import java.util.logging.Logger;
/**
* 项目组长批准请假
* 模拟当开发人员请假小于3天,组长比准
*
*
* <serviceTask id="servicetask3" name="项目组长同意" activiti:class="com.easyway.workflow.activiti.gateway.TeamLeaderServiceTask"></serviceTask>
* @author longgangbai
*
* 2011-12-17 上午09:07:37
*/
public class TeamLeaderServiceTask implements JavaDelegate {
private final Logger log = Logger.getLogger(TeamLeaderServiceTask.class.getName());
@Override
public void execute(DelegateExecution execution) throws Exception {
Thread.sleep(10000);
log.info("variavles=" + execution.getVariables());
execution.setVariable("项目组长", "请假天数小于3天,同意请假。");
log.info("项目组长,请假天数小于3天,同意请假。");
}
}
package com.easyway.workflow.activiti.gateway;
import java.util.logging.Logger;
/**
* execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
*
* <serviceTask id="servicetask4" name="项目总监同意" activiti:class="com.easyway.workflow.activiti.gateway.ProductBossServiceTask"></serviceTask>
*
* 项目总监审批过程
* @author longgangbai
*
* 2011-12-17 下午07:45:47
*/
public class ProductBossServiceTask implements JavaDelegate {
private final Logger log = Logger.getLogger(ProductBossServiceTask.class.getName());
@Override
public void execute(DelegateExecution execution) throws Exception {
Thread.sleep(10000);
log.info("variavles=" + execution.getVariables());
execution.setVariable("项目总监", "请假天数大约3天,同意请假。");
log.info("项目总监,请假天数大约3天,同意请假。");
}
}
package com.easyway.workflow.activiti.gateway;
import java.util.logging.Logger;
/**
* execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。
*自动执行
<serviceTask>元素,可以实现自动活动,语法如下所示:
<serviceTask id="serviceTaskId" name="serviceTaskName"
activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTaskClass"/>
其中,activiti:class属性为该结点对应的处理类,该类要求实现org.activiti.engine.delegate.JavaDelegate接口
* <serviceTask id="servicetask5" name="人事部门同意" activiti:class="com.easyway.workflow.activiti.gateway.HumanResouceServiceTask"></serviceTask>
*
* 人事部门审批过程
* @author longgangbai
*
* 2011-12-17 下午07:45:47
*/
public class HumanResouceServiceTask implements JavaDelegate {
private final Logger log = Logger.getLogger(HumanResouceServiceTask.class.getName());
@Override
public void execute(DelegateExecution execution) throws Exception {
Thread.sleep(10000);
log.info("variavles=" + execution.getVariables());
execution.setVariable("人事部门", "请假天数大约3天,同意请假。");
log.info("人事部门 ,请假天数大约3天,同意请假。");
}
}
package com.easyway.workflow.activiti.gateway;
import junit.framework.TestCase;
import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.test.ActivitiTestCase;
/**
* 主要是在测试之前做一些初始化工作,主要包括流程引擎实例
* 的构建,及其流程提供的基本服务。
* 目的:让开发者熟悉工作流使用过程使用的几个步骤
* 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.gateway;
import org.activiti.engine.runtime.ProcessInstance;
/**
* Activiti 5.6支持流程活动自动执行与手工触发执行。
* 其中,自动执行是指,在启动流程之前,准备流程所需要的控制流程进度的变量数据,
* 启动流程之后,无需外部干预,就能够按照预定义的流程执行;
* 过基于Activiti 5.6的<parallelGateway>、<serviceTask>、<receiveTask>、<userTask>元素
*
*
* 自动执行
*<serviceTask>元素,可以实现自动活动,语法如下所示:
*<serviceTask id="serviceTaskId" name="serviceTaskName"
*activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTaskClass"/>
*
* 其中,activiti:class属性为该结点对应的处理类,该类要求实现org.activiti.engine.delegate.JavaDelegate
* 接口,该接口定义如下所示:
*
* <pre>
* package org.activiti.engine.delegate;
* public interface JavaDelegate {
* void execute(DelegateExecution execution) throws Exception;
* }
* </pre>
* execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量
*
* 工作流模拟某公司请假流程情景如下:
* 1.开发人员请假流程,如果开发人员请假,如果请假天数小于3天,组长批准,人事批准即可请假。
* 2.如果请假大约三天,需要项目经理或者产品经理批准,并且项目总监批准
*
* 模拟自动审批:只需要启动一个流程实例,它会自动执行到结束。这种情况下,你不需要关注流
* 程的执行进度,而只需要把精力集中在每个结点的处理逻辑(通常是简单或者复杂的商业逻辑)上。
*
*
*
* @author longgangbai
*
* 2011-12-17 08:01:55
*/
public class AutomaticParallelGatewayTest extends AbstractTest {
private String deploymentId;
@Override
protected void initialize() throws Exception {
deploymentId = repositoryService.createDeployment()
.addClasspathResource("diagrams/AutoExecuteTask.bpmn20.xml")
.deploy().getId();
}
@Override
protected void destroy() throws Exception {
repositoryService.deleteDeployment(deploymentId, true);
}
/**
* 使用注解部署 工作流程
*/
@Deployment
public void testForkJoin() {
//根据流程ID获取流程实例
ProcessInstance pi = runtimeService.startProcessInstanceByKey("AutoExecuteTask");
//根据运行是服务检查是否执行的结束
assertEquals(true, pi.isEnded());
}
}
运行结果如下(运行单元测试之前必须启动H2数据库,否则报错):
2011-12-18 12:50:13 org.activiti.engine.ProcessEngines initProcessEnginFromResource
信息: initializing process engine for resource jar:file:/C:/activiti-rest/activiti-cfg.jar!/activiti.cfg.xml
2011-12-18 12:50:17 org.activiti.engine.impl.ProcessEngineImpl <init>
信息: ProcessEngine default created
2011-12-18 12:50:17 org.activiti.engine.ProcessEngines initProcessEnginFromResource
信息: initialised process engine default
2011-12-18 12:50:17 org.activiti.engine.impl.jobexecutor.JobAcquisitionThread run
信息: JobAcquisitionThread starting to acquire jobs
2011-12-18 12:50:17 org.activiti.engine.impl.bpmn.deployer.BpmnDeployer deploy
信息: Processing resource diagrams/AutoExecuteTask.bpmn20.xml
2011-12-18 12:50:17 org.activiti.engine.impl.bpmn.parser.BpmnParse parseDefinitionsAttributes
信息: XMLSchema currently not supported as typeLanguage
2011-12-18 12:50:17 org.activiti.engine.impl.bpmn.parser.BpmnParse parseDefinitionsAttributes
信息: XPath currently not supported as expressionLanguage
2011-12-18 12:50:27 com.easyway.workflow.activiti.gateway.DeveloperManagerServiceTask execute
信息: variavles={}
2011-12-18 12:50:27 com.easyway.workflow.activiti.gateway.DeveloperManagerServiceTask execute
信息: 项目经理,请假天数大约3天,同意请假。.
2011-12-18 12:50:37 com.easyway.workflow.activiti.gateway.ProductManagerServiceTask execute
信息: variavles={项目经理=请假天数大约3天,同意请假。}
2011-12-18 12:50:37 com.easyway.workflow.activiti.gateway.ProductManagerServiceTask execute
信息: 产品经理,请假天数大约3天,同意请假。
2011-12-18 12:50:47 com.easyway.workflow.activiti.gateway.ProductBossServiceTask execute
信息: variavles={项目经理=请假天数大约3天,同意请假。, 产品经理=请假天数大约3天,同意请假。}
2011-12-18 12:50:47 com.easyway.workflow.activiti.gateway.ProductBossServiceTask execute
信息: 项目总监,请假天数大约3天,同意请假。
2011-12-18 12:50:57 com.easyway.workflow.activiti.gateway.TeamLeaderServiceTask execute
信息: variavles={项目总监=请假天数大约3天,同意请假。, 项目经理=请假天数大约3天,同意请假。, 产品经理=请假天数大约3天,同意请假。}
2011-12-18 12:50:57 com.easyway.workflow.activiti.gateway.TeamLeaderServiceTask execute
信息: 项目组长,请假天数小于3天,同意请假。
2011-12-18 12:51:08 com.easyway.workflow.activiti.gateway.HumanResouceServiceTask execute
信息: variavles={项目总监=请假天数大约3天,同意请假。, 项目组长=请假天数小于3天,同意请假。, 项目经理=请假天数大约3天,同意请假。, 产品经理=请假天数大约3天,同意请假。}
2011-12-18 12:51:08 com.easyway.workflow.activiti.gateway.HumanResouceServiceTask execute
信息: 人事部门 ,请假天数大约3天,同意请假。
由上面运行结果可以看出:
1.XPath currently not supported as expressionLanguage:原因工作流activiti表达式UEL必须在JDK1.5+以上,其实是UEL在JDK1.6中提供,本人采用JDK1.5.
2.:/C:/activiti-rest/activiti-cfg.jar!/activiti.cfg.xml:全局activiti配置文件采用默认的配置文件。