使用Activiti服务
与Activiti引擎进行交互的方式是通过org.activiti.engine.ProcessEngine
类的实例公开的服务,以下代码段假定你拥有一个有效的Activiti环境,即你可以访问有效的org.activiti.engine.ProcessEngine
。如果你只想尝试下面的代码,则可以下载或克隆Activiti单元测试模板,将其导入IDE中,然后将testUserguideCode()
方法添加到org.activiti.MyUnitTest
单元测试中。
这个小教程的最终目标是要有一个能正常工作的业务流程,该流程模仿公司中一个简单的请假流程:
部署流程
与静态数据相关的所有内容(例如流程定义)都可以通过RepositoryService
访问,从概念上讲,每个此类静态数据都是Activiti引擎存储库的内容。
在src/test/resources/org/activiti/test
资源文件夹(或如果不使用单元测试模板的其他任何地方)中创建具有以下内容的新xml文件VacationRequest.bpmn20.xml
。
${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
management
${vacationApproved == 'true'}
${vacationApproved == 'false'}
Your manager has disapproved your vacation request for ${numberOfDays} days.
Reason: ${managerMotivation}
${employeeName}
${resendRequest == 'true'}
${resendRequest == 'false'}
为了使Activiti引擎知道此流程,我们必须先进行部署,部署意味着引擎将BPMN 2.0 xml解析为可执行文件,并将为部署中包含的每个流程定义添加新的数据库记录,这样,当引擎重新启动时,它仍然会知道所有已部署的流程:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
.addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
.deploy();
Log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());
启动流程实例
将流程定义部署到Activiti引擎后,我们可以从中启动新流程实例,对于每个流程定义,通常有许多流程实例,流程定义是蓝图,而流程实例是其运行时执行。
与流程的运行时状态相关的所有内容都可以在RuntimeService
中找到,有多种启动新流程实例的方法。在以下代码段中,我们使用在流程定义xml中定义的键来启动流程实例,我们还在流程实例启动时提供了一些流程变量,因为第一个用户任务的描述将在其表达式中使用它们。流程变量是常用的,因为它们赋予特定流程定义的流程实例以意义,通常,流程变量使流程实例彼此不同。
Map variables = new HashMap();
variables.put("employeeName", "Kermit");
variables.put("numberOfDays", new Integer(4));
variables.put("vacationMotivation", "I'm really tired!");
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);
// Verify that we started a new process instance
Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());
完成任务
该流程开始时,第一步将是用户任务,这是系统用户必须执行的步骤,通常,此类用户将有一个任务收件箱,其中列出了该用户需要完成的所有任务,以下代码段显示了如何执行这种查询:
// Fetch all tasks for the management group
TaskService taskService = processEngine.getTaskService();
List tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
Log.info("Task available: " + task.getName());
}
要继续该流程实例,我们需要完成此任务,对于Activiti引擎,这意味着你需要完成任务,以下片段显示了如何完成此操作:
Task task = tasks.get(0);
Map taskVariables = new HashMap();
taskVariables.put("vacationApproved", "false");
taskVariables.put("managerMotivation", "We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);
该流程实例现在将继续进行下一步,在此示例中,下一步允许员工填写可调整其原始休假请求的表格,员工可以重新提交休假请求,这将导致流程循环回到启动任务。
暂停和激活流程
可以暂停流程定义,流程定义被暂停后,将无法创建新的流程实例(将引发异常),通过RepositoryService
暂停流程定义:
repositoryService.suspendProcessDefinitionByKey("vacationRequest");
try {
runtimeService.startProcessInstanceByKey("vacationRequest");
} catch (ActivitiException e) {
e.printStackTrace();
}
要重新激活流程定义,只需调用repositoryService.activateProcessDefinitionXXX
方法之一。
也可以暂停流程实例,暂停后,该流程将无法继续执行(例如,完成任务会引发异常),并且不会执行任何作业(例如计时器),可以通过调用runtimeService.suspendProcessInstance
方法来挂起流程实例,通过调用runtimeService.activateProcessInstanceXXX
方法来再次激活流程实例。