BPMN 2.0介绍
阅读数:191 评论数:0
跳转到新版页面分类
python/Java
正文
一、简介
BPMN是一个广泛接受与支持的,展现流程的注记方法。
BPMN 2.0概要(schema)的根元素(root element)是definitions元素。在这个元素中,可以定义多个流程定义(然而我们建议在每个文件中,只有一个流程定义。这样可以简化之后的部署过程)。下面给出的是一个空流程定义。请注意definitions元素最少需要包含xmlns与targetNamespace声明。targetNamespace可以为空,它用于对流程定义进行分类。
<definitions
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:flowable="http://flowable.org/bpmn"
targetNamespace="Examples">
<process id="myProcess" name="My First Process">
..
</process>
</definitions>
1、process元素
有两个属性:
(1)id
必填属性,将映射为Flowable ProcessDefinition对象的key参数。可以使用RuntimeService中的startProcessInstanceByKey方法,使用id来启动这个流程定义的新流程实例。这个方法总会使用流程定义的最新部署版本。
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");
注意这与调用startProcessInstanceById方法不同。startProcessInstanceById方法的参数为Flowable引擎在部署时生成的字符串ID(可以通过调用processDefinition.getId()方法获取)。生成ID的格式为'key:version',长度限制为64字符。请注意限制流程key的长度,否则会抛出FlowableException异常,提示生成的ID过长。
(2)name
可选属性,将映射为ProcessDefinition的name参数。引擎本身不会使用这个参数。可以用于在用户界面上显示更友好的名字。
二、示例
1、用例
用例很简单:有一个公司,叫做BPMCorp。在BPMCorp中,由会计部门负责,每月需要为投资人撰写一份报告。在报告完成后,需要高层经理中的一人进行审核,然后才能发给所有投资人。
2、流程图
上面描述的业务流程可以使用Flowable Designer直接画出。但是在这个教程里我们自己写XML,这样可以学习更多。这个流程的图形化BPMN 2.0注记像是这样:
我们看到的是一个空启动事件,接下来是两个用户任务,最后是空结束事件。
3、xml格式
<definitions id="definitions"
targetNamespace="http://flowable.org/bpmn20"
xmlns:flowable="http://flowable.org/bpmn"
xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">
<process id="financialReport" name="Monthly financial report reminder process">
<startEvent id="theStart" />
<sequenceFlow id="flow1" sourceRef="theStart" targetRef="writeReportTask" />
<userTask id="writeReportTask" name="Write monthly financial report" >
<documentation>
Write monthly financial report for publication to shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>accountancy</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow2" sourceRef="writeReportTask" targetRef="verifyReportTask" />
<userTask id="verifyReportTask" name="Verify monthly financial report" >
<documentation>
Verify monthly financial report composed by the accountancy department.
This financial report is going to be sent to all the company shareholders.
</documentation>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>management</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
<sequenceFlow id="flow3" sourceRef="verifyReportTask" targetRef="theEnd" />
<endEvent id="theEnd" />
</process>
</definitions>
4、启动流程实例
要用给定的流程定义创建流程实例,需要首先部署(deploy)流程定义。部署流程定义意味着两件事:
(1)流程定义将会存储在Flowable引擎配置的持久化数据库中。因此部署业务流程保证了引擎在重启后也能找到流程定义。
(2)BPMN 2.0流程XML会解析为内存中的对象模型,供Flowable API使用。
部署有很多种方式,其中一种是通过下面展示的API。
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("FinancialReportProcess.bpmn20.xml")
.deploy();
现在可以使用在流程定义中定义的id启动新流程实例,请注意这个id在Flowable术语中被称作key。
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");
这会创建流程实例,并首先通过开始事件。在开始事件后,会沿着所有出口顺序流(在这个例子中只有一个)继续执行,并到达第一个任务('write monthly financial report 撰写月度财务报告')。这时,Flowable引擎会在持久化数据库中存储一个任务。同时也会解析并保存这个任务附加的分配用户或组。请注意,Flowable引擎会持续执行流程,直到到达等待状态(wait state),例如用户任务。在等待状态,流程实例的当前状态会存储在数据库中并保持,直到用户决定完成任务。这时,引擎会继续执行,直到遇到新的等待状态,或者流程结束。如果在这期间引擎重启或崩溃,流程的状态也仍在数据库中安全的保存。
用户任务活动是一个等待状态,因此startProcessInstanceByKey方法会在任务创建后返回。在这个例子里,这个任务分配给一个组。这意味着这个组的每一个成员都是处理这个任务的候选人(candidate)。
5、任务列表
现在可以通过如下代码获取这个任务:
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list();
请注意传递给这个操作的用户需要是accountancy组的成员。
也可以使用任务查询API ,用组名查得相同的结果。
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
因为这里我们使用相同的数据库,因此可以直接登录Flowable IDM,使用admin/test登录,创建两个新用户kermit与fozzie,并并将Access the workflow application(访问工作流应用)权限授予他们。然后创建两个组,命名为accountancy与management,并将fozzie添加至accountancy组,将kermit添加至management组。 然后以fozzie登录Flowable task应用。选择Task应用,再选择其Processes页面,选择'Monthly financial report (月度财务报告)',这样就可以启动我们的业务流程。
前面已经解释过,流程会执行直到第一个用户任务。因为登录为fozzie,所以可以看到在启动流程实例后,他有一个新的候选任务(candidate task)。选择Task页面来查看这个新任务。请注意即使流程是由其他人启动的,accountancy组中的每一个人仍然都能看到这个候选任务。
6、申领任务
会计师(accountancy组的成员)现在需要申领任务(claim)。申领任务后,这个用户会成为任务的执行人(assignee),这个任务也会从accountancy组的其他成员的任务列表中消失。可以通过如下代码实现申领任务:
taskService.claim(task.getId(), "fozzie");
这个任务现在在申领任务者的个人任务列表中。
List<Task> tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
在Flowable Task应用中,点击claim按钮会执行相同操作。这个任务会转移到登录用户的个人任务列表中。也可以看到任务执行人变更为当前登录用户。
7、完成任务
会计师(accountancy组的成员)现在需要开始撰写财务报告了。完成报告后,他就可以完成任务(complete),代表任务的所有工作都已完成。
taskService.complete(task.getId());
对于Flowable引擎来说,这是个外部信号,指示流程实例可以继续执行。Flowable会从运行时数据中移除任务,并沿着这个任务唯一的出口转移线(outgoing transition),将执行移至第二个任务('verification of the report 审核报告')。为第二个任务分配执行人的机制,与上面介绍的第一个任务使用的机制相同。唯一的区别是这个任务会分配给management组。
在演示设置中,完成任务可以通过点击任务列表中的complete按钮。因为Fozzie不是经理,我们需要登出Flowable Task应用,并用kermit(他是经理)登录。这样就可以在未分配任务列表中看到第二个任务。
8、结束流程
可以使用与之前完全相同的方式获取并申领审核任务。完成这个第二个任务会将流程执行移至结束事件,并结束流程实例。这个流程实例,及所有相关的运行时执行数据都会从数据库中移除。
也可以通过编程方式,使用historyService验证流程已经结束
HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
9、后续增强
(1)定义网关(gateway)使经理可以选择:驳回财务报告,并重新为会计师创建任务;或者接受报告。
(2)定义并使用变量(variables)存储或引用报告,并可以在表单中显示它。
(3)在流程结束处定义服务任务(service task),将报告发送给每一个投资人。
(4)等等。