现在我们有了业务流程的流程定义(process definition)。通过这个流程定义我们就可以创建一个流程实例(process instances)了。在这个用例中,一个流程实例将和每月财务报告的创建和批准项匹配。
为了能够通过一个流程定义创建一个流程实例,我们必须先将定义的流程发布(deploy),发布流程意味着两件事:
流程定义保存到Activiti引擎的持久化数据库中。通过发布业务流程,我们就能确保就算在引擎重启后也能够找到该流程的定义。
BPMN2.0流程定义文件将被解释到内存中,从而可以通过activiti的API执行相应的操作。
更详细的信息可以通过专门的发布流程章节获取。
就像专门的发布流程章节中提及的,可以通过多种方式去发布流程,以下是其中的一种:
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("org/activiti/examples/bpmn/usertask/FinancialReportProcess.bpmn20.xml")
.deploy();
现在我们可以通过在流程id(看XML流程定义文件中的第一行)去初始化一个流程实例了。注意这个id在Activiti的术语中称为key。
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");
一经上面的初始化将立即通过流程的start event,在start event.以后,紧跟着就是流出流向(在这个用例中只有一条)和到达第一个任务(撰写财务报告)。Activiti引擎将保存一个任务到数据库中。这时候附属于该任务的相关用户或用户组的作业也会被保存到数据库中。
任务创建后,处于等待接收状态,引擎将仅在下次接收到而外的触发调用后才会继续下去。在这个节点,任务是分派到用户组的,意指该用户组中的任何人都可以作为这个任务的候选者去执行这个任务。
现在我们可以通过taskService去获取用户的任务列表了。
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("fozzie").list();
因为流程定义中这个任务是定义为分派到用户组accountancy的,因此方法中传入的用户名参数"fozzie"必须是属于该用户组的用户:
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
也可以通过任务的查询API,如下获取用户组的任务:
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
上面描述的业务流程已经发布到了演示数据中。在运行ant demo.start后,以用户fozzie(他是一个会计师)身份登录到Activiti Explorer,选择PROCESSES页签,在列表的Action列中点击流程“Monthly financial report'”的“Start Process"链接去启动一个流程实例。如下图所示:
正如前面解解释的,流程将运行到第一个任务处。由于我们是以用户fozzie登录,故在我们启动了这个流程实例后,可以看到一个新的候选任务。我们这是切换到TASKS页签页去看看这个新任务(如下图),可以发现就算其他人启动的流程实例,所有属于用户组accountancy的用户都可以看到这个新的候选任务。
现在其中一个会计人员需要领取这个任务(claim the task)。通过领取任务操作,特定的用户就会成为这个任务的代理人(assignee),这是这个任务就会从用户组accountancy的其他所有用户的列表视图中消失。领取任务的调用代码如下:
taskService.claim(task.getId(), "fozzie");
现在这个任务成为了任务领取者的个人任务了。
List<Task> tasks = taskService.createTaskQuery().taskAssignee("fozzie");
通过Activiti Explorer界面点击claim按钮将执行相同的领取任务操作。现在这个任务将显示在任务领取者的个人任务列表中,如下图所示:
现在会计员可以开始撰写财务报表了,一但报表撰写完毕,就可以执行完成任务的操作将任务完成掉:
taskService.complete(task.getId());
对Activiti引擎去说,这是通知流程实例必须继续跑下去的额外信号。该任务的外出流向将被解析执行,引导到第二个任务(批准财务报告)。同样的原理,就像上面第一个任务所发生的事情一样将在第二个任务出发生,唯一不同的是这次任务将被分派到用户组management。
在上面的demo中,使它能够过点击complete按钮去完成任务的。因Frozzie不是管理者,所以我们需要注销并以kermit(他是管理者)用户登录。第二个任务现在就显示在待指定任务列表中了。如下图所示:
这个批准任务就像第一个任务的处理一样可以接受和领取。完成这个任务将导致流程执行到end event节点,在这个节点将终止该流程实例。该流程实例以及所有与其相关的运行时期的执行数据将会从数据库中删除。
可以通过 Activiti Probe去证实这些数据已被清除。因为表中已经没有任何流程的执行数据。
通过定义一个 timer start event 节点每月自动开始启动流程。
定义 gateways 节点执行条件判断。为此,管理者可以拒绝财务报表让会计师重建原去的任务。
通过声明和使用变量(variables),控制报告在表单的编辑权限。
通过在流程结束时定义一个service task任务将报告自动发送给所有股东。.
...