Flowable入门系列文章4-流程实例

1、启动一个流程实例

我们现在将流程定义部署到流程引擎,因此可以使用此流程定义作为蓝图来启动流程实例。

要启动流程实例,我们需要提供一些初始流程变量。通常情况下,当某个进程被自动触发时,您将通过呈现给用户的表单或通过REST API获取这些表单。在这个例子中,我们将保持简单并使用java.util.Scanner类在命令行上简单地输入一些数据:

Scanner scanner= new Scanner(System.in);
System.out.println("Who are you?");
String employee = scanner.nextLine();
System.out.println("How many holidays do you want to request?");
Integer nrOfHolidays = Integer.valueOf(scanner.nextLine());
System.out.println("Why do you need them?");
String description = scanner.nextLine();

接下来,我们可以通过RuntimeService启动一个流程实例。收集的数据以java.util.Map实例的形式传递,其中的关键字是稍后用于检索变量的标识符。流程实例使用密钥启动。此键匹配在BPMN 2.0 XML文件中设置的id属性,在此情况下为holidayRequest。
(注意:以后有很多方法可以启动一个流程实例,而不是使用一个键)

<process id="holidayRequest" name="Holiday Request" isExecutable="true">
RuntimeService runtimeService = processEngine.getRuntimeService();
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employee", employee);
variables.put("nrOfHolidays", nrOfHolidays);
variables.put("description", description);
ProcessInstance processInstance =
runtimeService.startProcessInstanceByKey("holidayRequest", variables);

当流程实例启动时,会创建一个执行并放入启动事件。从那里,这个执行遵循用户任务的顺序流程以供管理者批准,并执行用户任务行为。此行为将在数据库中创建一个任务,以后可以使用查询找到该任务。用户任务是等待状态,引擎将停止执行任何操作,返回API调用。

2、Sidetrack:事务性

在Flowable中,数据库事务对保证数据一致性和解决并发问题起着至关重要的作用。当您进行Flowable API调用时,默认情况下,所有内容都是同步的并且是同一事务的一部分。意思是,当方法调用返回时,事务将被启动并提交。

当一个流程实例启动时,从流程实例的开始到下一个等待状态将会有一个数据库事务。在这个例子中,这是第一个用户任务。当引擎到达这个用户任务时,状态被持久化到数据库,事务被提交并且API调用返回。

在Flowable中,当继续一个流程实例时,总是有一个数据库事务从前一个等待状态转到下一个等待状态。一旦持久化,数据可以在数据库中很长一段时间,甚至数年(如果必须的话),直到执行进一步采用流程实例的API调用。请注意,当流程实例处于等待状态时,不会消耗任何计算资源或内存资源,从而等待下一个API调用。

在这里的示例中,当第一个用户任务完成时,将使用一个数据库事务从用户任务通过专用网关(自动逻辑)直到第二个用户任务。或者直到另一条路的尽头。

3、查询和完成任务

在更现实的应用程序中,将会有一个用户界面,员工和经理可以登录并查看他们的任务列表。通过这些,他们可以检查存储为流程变量的流程实例数据,并决定他们想要处理的任务。在这个例子中,我们将通过执行通常位于驱动UI的服务调用后面的API调用来模拟任务列表。

我们还没有为用户任务配置分配。我们希望第一个任务去管理员组和第二个用户任务分配给假期的原始请求者。为此,请将candidateGroups属性添加到第一个任务:

<userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="managers"/>

而受让人属于第二个任务,如下所示。请注意,我们没有像上面的管理器值那样使用静态值,而是基于流程实例启动时所传递的流程变量的动态赋值:

<userTask id="holidayApprovedTask" name="Holiday approved" flowable:assignee="${employee}"/>

为了得到实际的任务列表,我们通过TaskService创建一个TaskQuery,并且配置查询只返回管理员组的任务:

TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
System.out.println("You have " + tasks.size() + " tasks:");
for (int i=0; i<tasks.size(); i++) {
System.out.println((i+1) + ") " + tasks.get(i).getName());
}

使用任务标识符,我们现在可以获得特定的流程实例变量,并在屏幕上显示实际的请求:

System.out.println("Which task would you like to complete?");
int taskIndex = Integer.valueOf(scanner.nextLine());
Task task = tasks.get(taskIndex - 1);
Map<String, Object> processVariables = taskService.getVariables(task.getId());
System.out.println(processVariables.get("employee") + " wants " +
processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");

运行的结果是这样的:
Flowable入门系列文章4-流程实例
现在可以完成任务。实际上,这通常意味着表单是由用户提交的。然后将表单中的数据作为流程变量传递。在这里,我们将通过在已完成的任务完成时向批准的变量传递一个映射(名称非常重要,因为稍后会在序列流的条件中使用!):

boolean approved = scanner.nextLine().toLowerCase().equals("y");
variables = new HashMap<String, Object>();
variables.put("approved", approved);
taskService.complete(task.getId(), variables);

该任务现在已经完成,并且基于批准的过程变量来选择离开专用网关的两个路径之一。

上面文章来自盘古BPM研究院:http://vue.pangubpm.com/
文章翻译提交:https://github.com/qiudaoke/flowable-userguide
了解更多文章可以关注微信公众号:
Flowable入门系列文章4-流程实例

上一篇:mysql相关优化


下一篇:MySQL学习笔记(三)