说说 jBPM 流程定义语言(11)—— 事件
2018-03-17 20:18
681 查看
事件(event)用来流程执行的过程中特定的“点”,例如“流程实例开始”、“状态活动结束”等,可以在这些“点”中注册相应的监听器(listener)。当流程实例执行到这些被监听的点时,就会执行监听器中代码逻辑。
事件与监听器没有显示在流程定义的图中,因为它们更注重内部逻辑。
通过实现 EventListener 接口,来编写一个事件监听器:
之前说到的 java、script、hql 以及 sql 等自助活动,都可以作为事件监听器来监听事件。
可以使用 on 元素为事件监听器分组并制定事件,on 元素可以嵌入到 process 元素或 process 元素下的任何流程活动中。
on 元素的属性:
对于转移(transition)的执行事件,我们只需在 transition 元素中嵌入相应的事件监听器即可 。
on 元素支持的子元素:
自定义的事件监听器指向我们编写的 Java 类,它具有以下独特的属性:
jPDL:
现在,我们在 LogListener 中实现记录流程运行的日志,这些日志都记录在流程变量中:
单元测试:
默认情况下,事件监听器只对当前定义的元素有效,即 propagation=”disable”。我们可以通过指定事件监听器的传播属性 propagation=”enabled”,让这个事件监听器可以对其监听元素的所有子元素有效。
修改刚才的流程定义文件:
事件监听器:
单元测试:
一个良好的设计习惯是:在事件监听器中捕获业务异常,并设置一些流程变量来标识这个异常,然后我们可以在流程定义中设置若干个 decision 活动,来选择一个能够处理异常的转移路径上。
事件与监听器没有显示在流程定义的图中,因为它们更注重内部逻辑。
通过实现 EventListener 接口,来编写一个事件监听器:
public interface EventListener extends Serializable { void notify(EventListenerExecution var1) throws Exception; }
之前说到的 java、script、hql 以及 sql 等自助活动,都可以作为事件监听器来监听事件。
可以使用 on 元素为事件监听器分组并制定事件,on 元素可以嵌入到 process 元素或 process 元素下的任何流程活动中。
on 元素的属性:
属性 | 类型 | 默认值 | 是否必需 | 描述 |
---|---|---|---|---|
event | start(开始事件)/end(结束事件) | 无 | 必需 | 事件名称 |
on 元素支持的子元素:
元素 | 数目 | 描述 |
---|---|---|
event-listener | 0..* | 指定自定义的事件监听器,它需要实现 EventListener 接口。 |
任意自动活动 | 0..* | 使用自动活动(java,script,hql…)作为事件监听器。 |
属性 | 类型 | 默认值 | 是否必需 | 描述 |
---|---|---|---|---|
propagation | enable、disabled、true、false、on、off | disabled | 可选 | 是否支持被传播的事件 |
continue | sync、async、exclusive | sync | 可选 | 是否可异步执行 |
1 监听事件
jPDL:
<?xml version="1.0" encoding="UTF-8"?> <process name="EventListener" xmlns="http://jbpm.org/4.4/jpdl"> <!-- 监听流程的启动事件 --> <on event="start"> <event-listener class="net.deniro.jbpm.test.eventListener.LogListener"> <!-- 为事件监听器注入 msg 值 --> <field name="msg"> <string value="start on process definition"/> </field> </event-listener 10758 > </on> <start g="345,119,48,48" name="start1"> <transition to="等待"/> </start> <state g="443,118,92,52" name="等待"> <!-- 捕获【等待】活动开始事件 --> <on event="start"> <event-listener class="net.deniro.jbpm.test.eventListener.LogListener"> <field name="msg"> <string value="start on activity wait"/> </field> </event-listener> </on> <!-- 捕获【等待】活动结束事件 --> <on event="end"> <event-listener class="net.deniro.jbpm.test.eventListener.LogListener"> <field name="msg"> <string value="end on activity wait"/> </field> </event-listener> </on> <transition to="停车"> <!-- 捕获【等待】活动转移事件 --> <event-listener class="net.deniro.jbpm.test.eventListener.LogListener"> <field name="msg"> <string value="take transition"/> </field> </event-listener> </transition> </state> <state g="589,120,92,52" name="停车"/> </process>
现在,我们在 LogListener 中实现记录流程运行的日志,这些日志都记录在流程变量中:
public class LogListener implements EventListener { String msg; @Override public void notify(EventListenerExecution execution) throws Exception { List<String> logs = (List<String>) execution.getVariable("logs"); if (logs == null) { logs = new ArrayList<>(); execution.setVariable("logs", logs); } logs.add(msg); execution.setVariable("logs", logs); } }
单元测试:
//发起实例 ProcessInstance processInstance = executionService.startProcessInstanceByKey ("EventListener"); //触发流程走到下一步 Execution execution = processInstance.findActiveExecutionIn("等待"); assertNotNull(execution);//在【等待】节点 //发出执行信号 executionService.signalExecutionById(execution.getId()); List<String> logs = (List<String>) executionService.getVariable(execution.getId(), "logs"); System.out.println("logs:" + logs); assertFalse(logs.isEmpty());
2 传播事件
触发事件支持从父元素传播到子元素。默认情况下,事件监听器只对当前定义的元素有效,即 propagation=”disable”。我们可以通过指定事件监听器的传播属性 propagation=”enabled”,让这个事件监听器可以对其监听元素的所有子元素有效。
修改刚才的流程定义文件:
<?xml version="1.0" encoding="UTF-8"?> <process name="EventListenerPropagation" xmlns="http://jbpm.org/4.4/jpdl"> <!-- 监听流程的启动事件 --> <on event="start"> <!-- 支持传播,因为是定义在全局,所以,所有活动的 start 事件都会被捕获 --> <event-listener class="net.deniro.jbpm.test.eventListener.LogListener2" propagation="enabled"> <!-- 为事件监听器注入 msg 值 --> <field name="msg"> <string value="start on "/> </field> </event-listener> </on> <start g="351,122,48,48" name="start1"> <transition to="等待"/> </start> <!-- wait 活动的 start 事件将被捕获 --> <state g="439,117,92,52" name="等待"> <transition to="停车"/> </state> <!-- park 活动的 start 事件将被捕获 --> <state g="558,118,92,52" name="停车"/> </process>
事件监听器:
public class LogListener2 implements EventListener { String msg; @Override public void notify(EventListenerExecution execution) throws Exception { List<String> logs = (List<String>) execution.getVariable("logs"); if (logs == null) { logs = new ArrayList<>(); execution.setVariable("logs", logs); } String actName=((ExecutionImpl)execution).getActivityName(); ////因为流程实例的 start 事件所对应的流程名称为 null(如果未设置的话), 所以这里需要做处理 logs.add(msg+((actName==null)?"process":actName)); execution.setVariable("logs", logs); } }
单元测试:
//发起实例 ProcessInstance processInstance = executionService.startProcessInstanceByKey ("EventListenerPropagation"); //触发流程走到下一步 Execution execution = processInstance.findActiveExecutionIn("等待"); assertNotNull(execution);//在【等待】节点 //发出执行信号 executionService.signalExecutionById(execution.getId()); //获取流程变量 List<String> logs = (List<String>) executionService.getVariable(processInstance.getId(), "logs"); System.out.println("logs:" + logs); assertEquals(3, logs.size()); //设定预期日志内容 List<String> expectedLogs = new ArrayList<String>(); expectedLogs.add("start on start1"); expectedLogs.add("start on 等待"); expectedLogs.add("start on 停车"); assertEquals(expectedLogs, logs);
3 处理异常事件
建议在事件监听器中处理异常事件,即监听那些预期可能会发生的异常事件,比如可以设置变量标识异常、发出邮件报告异常以及利用 JMS 消息发布异常等处理,然后让流程实例执行所期望的行为,或者抛出异常让事务失败,同时做出一些 “补偿” 操作,让流程实例回到异常发生前的状态。一个良好的设计习惯是:在事件监听器中捕获业务异常,并设置一些流程变量来标识这个异常,然后我们可以在流程定义中设置若干个 decision 活动,来选择一个能够处理异常的转移路径上。
相关文章推荐
- 说说 jBPM 流程定义语言(8)—— sub-process(子流程活动)
- 说说 jBPM 流程定义语言(1)—— process
- 说说 jBPM 流程定义语言(7)—— task(人工任务活动)
- 说说 jBPM 流程定义语言(9)—— 自定义活动
- 说说 jBPM 流程定义语言(5)—— fork - join (分支、聚合活动)
- 说说 jBPM 流程定义语言(6)—— end (结束活动)
- 说说 jBPM 流程定义语言(2)—— start 活动 (启动活动)
- 说说 jBPM 流程定义语言(3)—— state 活动 (状态活动)
- 一步一步学JBPM(2)——JPDL流程定义语言
- jBPM用户指南 第16章 jBPM流程定义语言 (转载)
- JBPM(三)--- JPDL 流程定义语言
- 一步一步学JBPM(2)——JPDL流程定义语言
- jbpm用户指南翻译:第16章 jBPM流程定义语言(JPDL)
- JBPM表达业务流程(流程定义语言)
- jBPM流程定义语言(JPDL)
- 一、工单流程JBPM-------JPDL流程定义语言
- jBPM流程定义语言(JPDL)
- JBPM4.4:流程定义语言和活动、事件
- JBPM(六)——掌握JBPM流程定义语言
- AgileFlow的流程定义语言