Activiti学习资料(流程活动自动与手工触发执行)

Activiti 5.3:流程活动自动与手工触发执行


Activiti 5.3支持流程活动自动执行与手工触发执行。其中,自动执行是指,在启动流程之前,准备流程所需要的控制流程进度的变量数据,启动流程之后,无需外部干预,就能够按照预定义的流程执行;手工触发执行是指,执行到流程中某个个结点后流程暂时停止运行,直到收到外部发送的信号以后,才会继续向前推进,这样情况可以更加精细地控制流程。

下面主要通过基于Activiti 5.3的<parallelGateway>、<serviceTask>、<receiveTask>、<userTask>元素来看一下。首先,我们在测试的过程中,用到JUnit 3.x,为了方便,这里给了一层封装,代码如下所示:

package org.shirdrn.workflow.activiti;

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;

/**
 * @author shirdrn
 */
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;
	
	@Override
	protected void setUp() throws Exception {
		super.setUp();
		if(processEngine==null) {
			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();
	}
	
	@Override
	protected void tearDown() throws Exception {
		super.tearDown();
		destroy();
	}
	
	protected abstract void initialize() throws Exception;
	
	protected abstract void destroy() throws Exception;
}

这里面,主要是在测试之前做一些初始化工作,主要包括流程引擎实例的构建,及其流程提供的基本服务。下面测试会用到该抽象类。

自动执行

<serviceTask>元素,可以实现自动活动,语法如下所示:

    <serviceTask id="serviceTaskId" name="serviceTaskName"
	activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTaskClass"/>

其中,activiti:class属性为该结点对应的处理类,该类要求实现org.activiti.engine.delegate.JavaDelegate接口,该接口定义如下所示:

package org.activiti.engine.delegate;

public interface JavaDelegate {
  
  void execute(DelegateExecution execution) throws Exception;

}

execute方法的参数DelegateExecution execution可以在流程中各个结点之间传递流程变量。

下面给出一个具体的例子:

自动执行的流程,如图所示:

Activiti学习资料(流程活动自动与手工触发执行)_第1张图片 

对应的流程定义文件为GatewayTest.testAutomaticForkJoin.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="AutomaticParalellBasedForkJoin" name="AutomaticParalellBasedForkJoin">
    <startEvent id="startevent7" name="Start"></startEvent>
    <parallelGateway id="parallelgateway12" name="Fork"></parallelGateway>
    <serviceTask id="servicetask3" name="Task 1" activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTask1"></serviceTask>
    <serviceTask id="servicetask4" name="Task 2" activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTask2"></serviceTask>
    <serviceTask id="servicetask5" name="Task 3" activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTask3"></serviceTask>
    <parallelGateway id="parallelgateway13" name="First Join"></parallelGateway>
    <serviceTask id="servicetask6" name="Task 4" activiti:class="org.shirdrn.workflow.activiti.gateway.ServiceTask4"></serviceTask>
    <parallelGateway id="parallelgateway14"></parallelGateway>
    <endEvent id="endevent7" name="End"></endEvent>
    <sequenceFlow id="flow45" name="" sourceRef="startevent7" targetRef="parallelgateway12"></sequenceFlow>
    <sequenceFlow id="flow46" name="" sourceRef="parallelgateway12" targetRef="servicetask3"></sequenceFlow>
    <sequenceFlow id="flow47" name="" sourceRef="parallelgateway12" targetRef="servicetask4"></sequenceFlow>
    <sequenceFlow id="flow48" name="" sourceRef="parallelgateway12" targetRef="servicetask5"></sequenceFlow>
    <sequenceFlow id="flow49" name="" sourceRef="servicetask3" targetRef="parallelgateway13"></sequenceFlow>
    <sequenceFlow id="flow50" name="" sourceRef="servicetask4" targetRef="parallelgateway13"></sequenceFlow>
    <sequenceFlow id="flow51" name="" sourceRef="servicetask5" targetRef="parallelgateway14"></sequenceFlow>
    <sequenceFlow id="flow52" name="" sourceRef="parallelgateway13" targetRef="servicetask6"></sequenceFlow>
    <sequenceFlow id="flow53" name="" sourceRef="servicetask6" targetRef="parallelgateway14"></sequenceFlow>
    <sequenceFlow id="flow54" name="" sourceRef="parallelgateway14" targetRef="endevent7"></sequenceFlow>
  </process>
</definitions>

上述流程定义中,一共定义了4个ServiceTask,模拟实现代码如下所示:

package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

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

public class ServiceTask1 implements JavaDelegate {

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

	@Override
	public void execute(DelegateExecution execution) throws Exception {
		Thread.sleep(10000);
		log.info("variavles=" + execution.getVariables());
		execution.setVariable("task1", "I am task 1");
		log.info("I am task 1.");		
	}
}
package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

public class ServiceTask2 implements JavaDelegate {

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

	@Override
	public void execute(DelegateExecution execution) throws Exception {
		Thread.sleep(10000);
		log.info("variavles=" + execution.getVariables());
		execution.setVariable("task2", "I am task 2");
		log.info("I am task 2.");
	}
}

package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

public class ServiceTask3 implements JavaDelegate {

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

	@Override
	public void execute(DelegateExecution execution) throws Exception {
		Thread.sleep(10000);
		log.info("variavles=" + execution.getVariables());
		execution.setVariable("task3", "I am task 3");
		log.info("I am task 3.");		
	}
}

package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

public class ServiceTask4 implements JavaDelegate {

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

	@Override
	public void execute(DelegateExecution execution) throws Exception {
		Thread.sleep(10000);
		log.info("variavles=" + execution.getVariables());
		execution.setVariable("task4", "I am task 4");
		log.info("I am task 4.");	
	}
}

测试代码,如下所示:

package org.shirdrn.workflow.activiti.gateway;

import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.test.Deployment;
import org.shirdrn.workflow.activiti.AbstractTest;

/**
 * @author shirdrn
 */
public class AutomaticParallelGatewayTest extends AbstractTest {

	private String deploymentId;
	
	@Override
	protected void initialize() throws Exception {
		deploymentId = repositoryService.createDeployment()
			.addClasspathResource("diagrams/GatewayTest.testAutomaticForkJoin.bpmn20.xml")
			.deploy().getId();
	}

	@Override
	protected void destroy() throws Exception {
		repositoryService.deleteDeployment(deploymentId, true);
	}
	
	@Deployment
	public void testForkJoin() {
		ProcessInstance pi = runtimeService.startProcessInstanceByKey("AutomaticParalellBasedForkJoin");
		assertEquals(true, pi.isEnded());
	}
}

只需要启动一个流程实例,它会自动执行到结束。这种情况下,你不需要关注流程的执行进度,而只需要把精力集中在每个结点的处理逻辑(通常是简单或者复杂的商业逻辑)上,运行结果如下所示:

2011-3-23 11:50:12 org.shirdrn.workflow.activiti.gateway.ServiceTask1 execute
信息: variavles={}
2011-3-23 11:50:12 org.shirdrn.workflow.activiti.gateway.ServiceTask1 execute
信息: I am task 1.
2011-3-23 11:50:22 org.shirdrn.workflow.activiti.gateway.ServiceTask2 execute
信息: variavles={task1=I am task 1}
2011-3-23 11:50:22 org.shirdrn.workflow.activiti.gateway.ServiceTask2 execute
信息: I am task 2.
2011-3-23 11:50:32 org.shirdrn.workflow.activiti.gateway.ServiceTask4 execute
信息: variavles={task1=I am task 1, task2=I am task 2}
2011-3-23 11:50:32 org.shirdrn.workflow.activiti.gateway.ServiceTask4 execute
信息: I am task 4.
2011-3-23 11:50:42 org.shirdrn.workflow.activiti.gateway.ServiceTask3 execute
信息: variavles={task1=I am task 1, task2=I am task 2, task4=I am task 4}
2011-3-23 11:50:42 org.shirdrn.workflow.activiti.gateway.ServiceTask3 execute
信息: I am task 3.

手工触发执行

通过<receiveTask>和<userTask>元素都可以实现流程的手工触发执行。

基于<receiveTask>

实现的流程,如图所示:

对应的流程定义文件Task.ReceiveTask.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="MyReceiveTask" name="MyReceiveTask">
    <startEvent id="startevent4" name="Start"></startEvent>
    <receiveTask id="receivetask1" name="Check bank">
      <extensionElements>
        <activiti:executionListener event="start" class="org.shirdrn.workflow.activiti.task.CheckBankReceiveTask"></activiti:executionListener>
      </extensionElements>
    </receiveTask>
    <receiveTask id="receivetask2" name="Check merchant">
      <extensionElements>
        <activiti:executionListener event="start" class="org.shirdrn.workflow.activiti.task.CheckMerchantReceiveTask"></activiti:executionListener>
      </extensionElements>
    </receiveTask>
    <endEvent id="endevent5" name="End"></endEvent>
    <sequenceFlow id="flow16" name="" sourceRef="startevent4" targetRef="receivetask1"></sequenceFlow>
    <sequenceFlow id="flow17" name="" sourceRef="receivetask1" targetRef="receivetask2"></sequenceFlow>
    <sequenceFlow id="flow18" name="" sourceRef="receivetask2" targetRef="endevent5"></sequenceFlow>
  </process>
</definitions>

上述流程定义中,对应的两个处理类,代码分别如下所示:

package org.shirdrn.workflow.activiti.task;

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

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

public class CheckBankReceiveTask implements JavaDelegate {

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

	@SuppressWarnings("unchecked")
	@Override
	public void execute(DelegateExecution execution) throws Exception {
		log.info("i am CheckBankReceiveTask.");
		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 org.shirdrn.workflow.activiti.task;

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

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

public class CheckMerchantReceiveTask implements JavaDelegate {

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

上面还用到一个org.shirdrn.workflow.activiti.subprocess.Merchant类,该类必须支持序列化,如下所示: 

package org.shirdrn.workflow.activiti.subprocess;

import java.io.Serializable;

public class Merchant implements Serializable {
	private static final long serialVersionUID = 1L;
	public Merchant(String merchantId, int priority, short serviceType, short status) {
		super();
		this.merchantId = merchantId;
		this.priority = priority;
		this.serviceType = serviceType;
		this.status = status;
	}
	public Merchant(String merchantId) {
		this(merchantId, -1, (short)0, (short)0);
	}
	private String merchantId;
	private int priority = -1;
	private short serviceType = 0;
	private short status = 0;
	public String getMerchantId() {
		return merchantId;
	}
	public void setMerchantId(String merchantId) {
		this.merchantId = merchantId;
	}
	public int getPriority() {
		return priority;
	}
	public void setPriority(int priority) {
		this.priority = priority;
	}
	public short getServiceType() {
		return serviceType;
	}
	public void setServiceType(short serviceType) {
		this.serviceType = serviceType;
	}
	public short getStatus() {
		return status;
	}
	public void setStatus(short status) {
		this.status = status;
	}
	@Override
	public String toString() {
		return "Merchant[" + merchantId + "]";
	}
}

测试用例,代码如下所示

package org.shirdrn.workflow.activiti.task;

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

import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.shirdrn.workflow.activiti.AbstractTest;
import org.shirdrn.workflow.activiti.subprocess.Merchant;

/**
 * @author shirdrn
 */
public class MyReceiveTaskTest extends AbstractTest {

	@Override
	protected void initialize() throws Exception {
		Deployment deployment = repositoryService
		.createDeployment()
		.addClasspathResource(
				"diagrams/Task.ReceiveTask.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", new 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("MyReceiveTask", 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());
	}

}

运行结果如下所示:

2011-3-23 12:51:35 org.shirdrn.workflow.activiti.task.CheckBankReceiveTask execute
信息: i am CheckBankReceiveTask.
in : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=Merchant[ICBC], maxTransCount=1000000, in={}, out={}}
2011-3-23 12:51:35 org.shirdrn.workflow.activiti.task.CheckMerchantReceiveTask execute
信息: i am CheckMerchantReceiveTask.
in : {protocol=UM32, repository=10.10.38.99:/home/shirdrn/repository, merchant=Merchant[ICBC], maxTransCount=1000000, type=receiveTask, in={}, out={}}

基于<userTask>

实现的流程,如图所示:

Activiti学习资料(流程活动自动与手工触发执行)_第2张图片

对应的流程定义文件,如下所示:


<?xml version="1.0" encoding="UTF-8"?>
<definitions id="definitions"
	xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn"
	targetNamespace="Umpay">
	<process id="ParalellBasedForkJoin">
		<startEvent id="theStart" />
		<sequenceFlow id="flow1" sourceRef="theStart" targetRef="fork" />
		<parallelGateway id="fork" name="Fork" />
		<sequenceFlow sourceRef="fork" targetRef="task1" />
		<sequenceFlow sourceRef="fork" targetRef="task2" />
		<sequenceFlow sourceRef="fork" targetRef="task3" />
		<userTask id="task1" name="Task 1">
			<extensionElements>
				<activiti:taskListener event="complete"
					class="org.shirdrn.workflow.activiti.gateway.Task1Listener" />
			</extensionElements>
		</userTask>
		<sequenceFlow sourceRef="task1" targetRef="firstJoin" />
		<userTask id="task2" name="Task 2">
			<extensionElements>
				<activiti:taskListener event="complete"
					class="org.shirdrn.workflow.activiti.gateway.Task2Listener" />
			</extensionElements>
		</userTask>
		<sequenceFlow sourceRef="task2" targetRef="firstJoin" />
		<userTask id="task3" name="Task 3">
			<extensionElements>
				<activiti:taskListener event="complete"
					class="org.shirdrn.workflow.activiti.gateway.Task3Listener" />
			</extensionElements>
		</userTask>
		<sequenceFlow sourceRef="task3" targetRef="secondJoin" />
		<parallelGateway id="firstJoin" name="First Join" />
		<sequenceFlow sourceRef="firstJoin" targetRef="task4" />
		<userTask id="task4" name="Task 4">
			<extensionElements>
				<activiti:taskListener event="complete"
					class="org.shirdrn.workflow.activiti.gateway.Task4Listener" />
			</extensionElements>
		</userTask>
		<sequenceFlow sourceRef="task4" targetRef="secondJoin" />
		<parallelGateway id="secondJoin" />
		<sequenceFlow sourceRef="secondJoin" targetRef="theEnd" />
		<endEvent id="theEnd" />
	</process>
</definitions>

我们看一下上述定义中,如下配置片段:

		<userTask id="task1" name="Task 1">
			<extensionElements>
				<activiti:taskListener event="complete"
					class="org.shirdrn.workflow.activiti.gateway.Task1Listener" />
			</extensionElements>
		</userTask>

<activiti:taskListener>元素的event属性,它一共包含三种事件:"create"、"assignment"、"complete",分别表示结点执行处理逻辑的时机为:在处理类实例化时、在结点处理逻辑被指派时、在结点处理逻辑执行完成时,可以根据自己的需要进行指定。

上述流程定义中,4个任务结点对应的处理类,代码分别如下所示:

package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

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

public class Task1Listener implements TaskListener {

	private final Logger log = Logger.getLogger(Task1Listener.class.getName());
	
	@Override
	public void notify(DelegateTask delegateTask) {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("I am task 1.");
	}
}


package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

public class Task2Listener implements TaskListener {

	private final Logger log = Logger.getLogger(Task2Listener.class.getName());
	
	@Override
	public void notify(DelegateTask delegateTask) {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("I am task 2.");
	}
}

package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

public class Task3Listener implements TaskListener {

	private final Logger log = Logger.getLogger(Task3Listener.class.getName());
	
	@Override
	public void notify(DelegateTask delegateTask) {
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("I am task 3.");
	}
}

package org.shirdrn.workflow.activiti.gateway;

import java.util.logging.Logger;

public class Task4Listener implements TaskListener {

	private final Logger log = Logger.getLogger(Task4Listener.class.getName());
	
	@Override
	public void notify(DelegateTask delegateTask) {
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.info("I am task 4.");
	}
}

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

package org.shirdrn.workflow.activiti.gateway;

import java.util.Date;
import java.util.List;

import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.activiti.engine.test.Deployment;
import org.shirdrn.workflow.activiti.AbstractTest;

/**
 * @author shirdrn
 */
public class ParallelGatewayTest extends AbstractTest {

	private String deploymentId;
	private Date start = null;
	private Date end = null;
	
	@Override
	protected void initialize() throws Exception {
		deploymentId = repositoryService.createDeployment()
			.addClasspathResource("diagrams/GatewayTest.testForkJoin.bpmn20.xml")
			.deploy().getId();
	}

	@Override
	protected void destroy() throws Exception {
		repositoryService.deleteDeployment(deploymentId, true);
	}
	
	@Deployment
	public void testUnbalancedForkJoin() {
		ProcessInstance pi = runtimeService.startProcessInstanceByKey("ParalellBasedForkJoin");
		TaskQuery query = taskService.createTaskQuery().processInstanceId(pi.getId()).orderByTaskName().asc();

		List<Task> tasks = query.list();		
		assertEquals(3, tasks.size());
		start = new Date();
		for(Task task : tasks) {
			taskService.complete(task.getId());
			end = new Date();
			System.out.println("" + (end.getTime()-start.getTime()) + "ms.");
		}

		tasks = query.list();
		assertEquals(1, tasks.size());
		for(Task task : tasks) {
			taskService.complete(task.getId());
			end = new Date();
			System.out.println("" + (end.getTime()-start.getTime()) + "ms.");
		}
		end = new Date();
		System.out.println("" + (end.getTime()-start.getTime()) + "ms.");
	}
}

运行结果如下所示:

2011-3-23 12:50:09 org.shirdrn.workflow.activiti.gateway.Task1Listener notify
信息: I am task 1.
10031ms.
2011-3-23 12:50:19 org.shirdrn.workflow.activiti.gateway.Task2Listener notify
信息: I am task 2.
20078ms.
2011-3-23 12:50:24 org.shirdrn.workflow.activiti.gateway.Task3Listener notify
信息: I am task 3.
25093ms.
2011-3-23 12:50:29 org.shirdrn.workflow.activiti.gateway.Task4Listener notify
信息: I am task 4.
30172ms.
30172ms.




你可能感兴趣的:(exception,String,object,活动,Class,Deployment)