基于jBPM4的临时动态性需求研究
基于jBPM4的临时动态性需求研究? http://www.chinaaet.com/article/index.aspx?id=22162
??? 节点2的处理人(假设是王二)办理完毕之后,将任务提交,此时任务到达了节点3(假设李三办理),这时李三就会收到一个待办任务,在李三还没有办理之前,王二突然发现,有1个业务数据填写错误,或者粘贴的附件错误,这时王二需要将发送给李三的任务撤销,重新更正数据后或修改粘贴的附件后再发送给李三审批。此外,假设节点3的办理人有2个人(李三和赵五),那么王二需要在运行期间根据业务特性手动地选择任务是提交给李三还是赵五,但由于王二的误操作,把本来应该发给赵五的办理任务错发送给了李三,此时,在李三办理之前,王二也可以将发送给李三的任务撤销,然后重新发送给赵五。
??? 对于上述模拟的撤销,jBPM4解决思路如下:
??? (1)删除需要撤销的任务实例及其与此任务实例相关的所有工作流实例。在文件TaskServiceImpl.java中,jBPM4提供了级联删除任务实例的相关方法:
??? public void deleteTaskCascade(String taskId) {
??????? commandService.execute(new DeleteTaskCmd(taskId,true));
??? }
??? (2)修改当前任务实例的状态。即将张三的已经办理完毕的节点2对应的TaskInstance的状态更改为待办状态:(Task.STATE_OPEN)
??? task.setState(ask.STATE_OPEN);
??? taskService.saveTask(task);
3.3 任意回退
??? 回退作为审批流最常见的需求,每1个审批环节都有可能会有审批通过、不通过2种情况。审批不通过时,一般是回退到上一个环节,但是在某些情况下,有可能跨环节回退,而到底回退到哪个环节,可以由用户根据业务需求进行自定义,并且在回退环节工作完成之后,其下一步的方向也可以由用户自定义。下面根据各种不同的回退分别模拟并给出解决思路。
3.3.1 串行流程
??? 串行流程,最直接的方式就是在需要回退的各个节点之间建立回退线,如图2所示。如果需要从节点4回退到节点2,则直接在节点4之后加1个分支决策节点,连接2个分支,1个是流向节点5,1个是返回节点2。
??? 对于节点2,在jBPM4中,其参与模式又分为4种:task-assignee(assignee user、assignee expression)、task candidates(candidate-groups、candidate-users)、task assignment handler、task swimlanes。
??? (1)task-assignee任务的办理人的值可以直接指向1个特指的用户的ID或者1个关联到业务中某个特指用户的表达式(如order.owner)。此时,如果assignee赋予了1个特指用户的ID,回退时不用做任何处理;如果assignee赋予了1个业务表达式,在回退时,需要保证业务表达式的运算逻辑能够正确执行。
??? (2)如果task candidates任务的办理人为几个特定的组的集合或者用户的集合,实际上就是俗称的“竞办”。这样的任务被称为groupTask,必须被某一个组或者用户拾取才能进行办理,因此,如果回退到这样的节点时,需要把任务回退给当时的拾取人。而拾取人需要到HistoryTask和HistoryDetailImpl 2个实体对应的历史库中取得。
? ???? (3)task assignment handler任务的办理人通过用户自己编写的代码来实现,当回退到这样的节点时,也不需要做特殊处理,只要保证自己的代码(AssignmentHandler)在执行回退逻辑时同样能够正确执行即可。
??? (4)task swimlanes任务的办理人为“泳道”,回退到这样的节点时,任务的办理人可以自动取得,同样不需要做任何处理。
??? 以上4种情况,在回退之后的处理又分为2种情况:一种是按照原来的路径重新执行,即节点2→节点3→节点4;另一种是,节点2办理完毕后,直接返回给节点4。对于第1种情况,不需要做处理。而对于第2种情况,由于在节点2和节点4之间并没有一个转移存在,因此jBPM4也没有提供支持。针对这种情况可以通过动态路由(即动态创建转移)的思路来实现(具体实现思路见第4节),实际上回退也可以用动态创建转移来实现,但不用画回退线了。
3.3.2 M选N分支流程
??? M选N分支流程中,N必须满足M>N?叟1,假设回退前流程的执行路径为节点1→节点2→节点4→节点5,如图3所示,此时回退有2种情况:
??? (1)由节点5回退到节点1,而节点1在进行业务数据的修改后,直接返回给节点5的处理人进行办理或审批。
??? (2)由节点5回退到节点1,而节点1在进行业务数据的修改后,重新按照节点1→节点2→节点4→节点5的路径再执行1遍。
??? 情况(2)与情况(1)不同的是:在回退之后继续审批时,需要考虑分支节点的决策条件,在自动决策时要保证决策逻辑正确执行;在人工决策时,需要记录原来的执行路径(保证重走节点1→节点2→节点4→节点5)。
3.3.3 同步分裂、“与”汇聚流程
??? 同步分裂、“与”汇聚流程如图4所示,回退前执行的路径为节点1→节点2→(节点3、节点4)→节点5→节点6。此时回退有4种不同的情况:
??? (1)由节点6(或节点5)回退到节点2(或节点1),节点2重新办理完毕后,直接返回给节点6的处理人进行办理或审批。
??? (2)由节点6(或节点5)回退到节点2(或节点1),节点2重新办理完毕后,重新按照节点2→(节点3、节点4)→节点5→节点6的路径再次执行1遍。
??? (3)由节点6(或节点5)回退到节点3(或节点4),节点3(或节点4)办理完毕后,直接返回给节点6。
??? (4)由节点6(或节点5)回退到节点3(或节点4),节点3(或节点4)办理完毕后,按照节点3(或节点4)→节点5→节点6的执行路径,再次执行。
??? 情况(1)、(2)和(3)处理起来没有什么问题。但情况4中,当流程由节点6回退到节点3,节点3办理完毕后,重走路径节点3→节点5→节点6时,在“与节点”的“与”运算逻辑就会无法执行,因为另1个“与”分支(节点4)并没有新的实例产生,流程就会僵死此处。所以可以通过修改JoinActivity.java这个类文件中的方法:
??? protected boolean isComplete(List<executionimpl> joined
Executions,Activity activity)
在此方法中加入对该情况的处理代码即可。
3.3.4 同步分裂、“或”汇聚流程
??? 同步分裂、“或”汇聚流程如图5所示,回退前执行的路径为节点1→节点2→(节点3、节点4)→节点5→节点6。此时回退同样有4种不同的情况:
??? (1)由节点6(或节点5)回退到节点2(或节点1),节点2重新办理完毕后,直接返回给节点6的处理人进行办理或审批。
??? (2)由节点6(或节点5)回退到节点2(或节点1),节点2重新办理完毕后,重新按照节点2→(节点3、节点4)→节点5→节点6的路径再次执行1遍。
??? (3)由节点6(或节点5)回退到节点3(或节点4),节点3(或节点4)办理完毕后,直接返回给节点6。
??? (4)由节点6(或节点5)回退到节点3(或节点4),节点3(或节点4)办理完毕后,按照节点3→节点5→节点6的执行路径,再次执行。
??? 由于是“或”汇聚,因此在实现上不需要做任何其他处理了。
??? 综合以上情况,回退本身在理论上有各种各样的情况存在,再加上业务的回退(或者业务逻辑补偿,如果需要就必须在流程的每个环节进行业务快照的备份,在回退时调用这个快照进行补偿),此时回退可以说是整个流程体系中最复杂的。但是在真实的业务情况中,有些可能是根本不会出现或者很少出现,因此要考虑的是能不能通过变通的方式处理。
4 动态路由的思路
??? 针对于特定的业务实例,有时需要在原本没有转移关系的环节之间进行特定的跳转,例如在图1中的串行流程中(1-2-3-4-5),节点4与节点2之间是没有任何转移存在的,但是针对于某个运行期的特定业务实例,临时要求环节直接从节点4回退跳转到节点2(而略过了节点3)。此时就需要在节点4和节点2之间由程序动态地创建一个转移(transition),并设定为优先级最高,如图6所示。
??? 因此在执行takeTransition( )方法时,按照优先级将优先执行动态创建的转移,然后对外暴露1个jumpTransition(String destinationActivityName)方法给客户端。应用jBPM4实现时可按照如下步骤进行扩展:
??? (1)参照文件CompleteTaskCmd.java扩展开发用于跳转的cmd:JumpTaskCmd。
??? (2)参照文件TransitionStartActivity.java的原子操作,定制开发用于跳转的原子操作JumpTransitionStartActivity。
??? 由于jBPM4中的执行动作都是基于Command模式实现的,因此在扩展开发自己的跳转动作时,就可以做到对jBPM4本身的代码不做侵入修改而实现。这种临时建立动态路由的思路不仅可以用于回退,同样可以用于重新操作后的跳转的实现。
??? jBPM作为目前应用最广泛的开源工作流产品,其最新的第4版有着很好的架构及扩展性。但是由于国外的流程应用与国内的应用有所不同,因此要想让jBPM4更好地满足国内的流程应用的需求,还需要做一定的定制开发。本文针对国内的流程应用的典型特点进行了较详细的分析,特别针对临时动态性需求的各种情况,给出了基于jBPM4的解决思路(限于篇幅文中并没有给出很详细的可以运行的代码)。本文所做的工作只是工作流应用技术研究的一小部分,还有很多方面需要继续学习和实践,需要进行深入的研究。
参考文献
[1] 范玉顺.工作流管理技术基础[M].北京:清华大学出版社,2001.
[2] WfMC-TC00-1003v1. 1. The workflow reference model[S]. 1995.
[3] JBoss官方.jBPM Documentation[EB/OL].http://www.jboss.org/jbossjbpm.2009-09.
[4] 胡长城.工作流讲解[EB/OL].www.javafox.org.2009-09.