使用JBPM实现动态会签

目前有很多实现动态会签的文章,但是给人感觉不是很优雅,下面介绍一种实现方式。
1、流程定义文件:
xml 代码
 
  1. <process-definition  
  2. xmlns="urn:jbpm.org:jpdl-3.1" name="foreach">  
  3. <start-state name="start">  
  4. <task name="one">  
  5. </task>  
  6. <transition name="a" to="foreachf"></transition>  
  7. </start-state>  
  8. <node name="foreachf">  
  9. <action class="com.framework.workflow.jbpm.ForEachFork">  
  10. <foreach>#{bpm_assignees}</foreach>  
  11. <var>reviewer</var>  
  12. </action>  
  13. <transition name="review" to="review"></transition>  
  14. </node>  
  15. <task-node name="review">  
  16. <task name="reviewTask">  
  17. <assignment class="com.framework.workflow.jbpm.DefaultAssignment">  
  18. <actor>#{reviewer}</actor>  
  19. </assignment>  
  20. </task>  
  21. <transition name="reject" to="endreview">  
  22. <action class="com.framework.workflow.jbpm.JoinEndForkedTokens" />  
  23. </transition>  
  24. <transition name="approve" to="endreview"></transition>  
  25. </task-node>  
  26. <join name="endreview">  
  27. <transition name="toend" to="end1"></transition>  
  28. </join>  
  29. <end-state name="end1"></end-state>  
  30. </process-definition>   

在这里我们从node节点动态生成任务节点,会签时当有一个是reject时便结束所有节点。
2、动态派生ForEachFork代码:
java 代码
 
  1. public class ForEachFork implements ActionHandler  
  2. {  
  3. private Element foreach;  
  4. private String var;  
  5. //测试数据  
  6. private static Map map = new HashMap();  
  7. static{  
  8. List list = new ArrayList();  
  9. list.add("1234");  
  10. list.add("2345");  
  11. list.add("3456");  
  12. map.put("bpm_assignees", list);  
  13. }  
  14.   
  15. /** 
  16. * 
  17.  
  18. 为每个元素创建一个分支 
  19.  
  20. * 
  21. * @param executionContext 
  22. * @throws Exception 
  23. */  
  24. @SuppressWarnings("unchecked")  
  25. public void execute(final ExecutionContext executionContext)  
  26. throws Exception  
  27. {  
  28.   
  29.   
  30. if (foreach == null)  
  31. {  
  32. throw new WorkflowException("forEach has not been provided");  
  33. }  
  34.   
  35. List forEachColl = null;  
  36. String forEachCollStr = foreach.getTextTrim();  
  37.   
  38. if (forEachCollStr != null)  
  39. {  
  40. if (forEachCollStr.startsWith("#{"))  
  41. {  
  42. String expression = forEachCollStr.substring(2, forEachCollStr.length() -1);  
  43. forEachColl = (List)map.get(expression);  
  44.   
  45. }  
  46.   
  47. }  
  48.   
  49. if (var == null || var.length() == 0)  
  50. {  
  51. throw new WorkflowException("forEach variable name has not been provided");  
  52. }  
  53.   
  54. //  
  55. // 创建分支  
  56. //  
  57.   
  58. Token rootToken = executionContext.getToken();  
  59. Node node = executionContext.getNode();  
  60. List forkTransitions = new ArrayList();  
  61. // 为每一个元素创建一个token  
  62. for (int i = 0; i < node.getLeavingTransitions().size(); i++)  
  63. {  
  64. Transition transition = (Transition) node.getLeavingTransitions().get(i);  
  65. for (int iVar = 0; iVar < forEachColl.size(); iVar++)  
  66. {  
  67. // 为每一个新token创建一个path  
  68. String tokenName = getTokenName(rootToken, transition.getName(), iVar);  
  69. Token loopToken = new Token(rootToken, tokenName);  
  70. loopToken.setTerminationImplicit(true);  
  71. executionContext.getJbpmContext().getSession().save(loopToken);  
  72.   
  73. //赋予一个新变量  
  74. final ExecutionContext newExecutionContext = new ExecutionContext(loopToken);  
  75. newExecutionContext.getContextInstance().createVariable(var, forEachColl.get(iVar), loopToken);  
  76.   
  77. // 记录下每一transition  
  78. ForkedTransition forkTransition = new ForkedTransition();  
  79. forkTransition.executionContext = newExecutionContext;  
  80. forkTransition.transition = transition;  
  81. forkTransitions.add(forkTransition);  
  82. }  
  83. }  
  84. //  
  85. // 转向下一个节点  
  86. //  
  87. for (ForkedTransition forkTransition : forkTransitions)  
  88. {  
  89. node.leave(forkTransition.executionContext, forkTransition.transition);  
  90. }  
  91. }  
  92. /** 
  93. * 
  94.  
  95. 获得分支token name 
  96.  
  97. * 
  98. * @param parent 
  99. * @param transitionName 
  100. * @return 
  101. */  
  102. protected String getTokenName(Token parent, String transitionName, int loopIndex)  
  103. {  
  104. String tokenName = null;  
  105. if (transitionName != null)  
  106. {  
  107. if (!parent.hasChild(transitionName))  
  108. {  
  109. tokenName = transitionName;  
  110. }  
  111. else  
  112. {  
  113. int i = 2;  
  114. tokenName = transitionName + Integer.toString(i);  
  115. while (parent.hasChild(tokenName))  
  116. {  
  117. i++;  
  118. tokenName = transitionName + Integer.toString(i);  
  119. }  
  120. }  
  121. }  
  122. else  
  123. {  
  124. // 没有转向  
  125. int size = ( parent.getChildren()!=null ? parent.getChildren().size()+1 : 1 );  
  126. tokenName = Integer.toString(size);  
  127. }  
  128. return tokenName + "." + loopIndex;  
  129. }  
  130.   
  131.   
  132.   
  133. /** 
  134. * Fork Transition 
  135. */  
  136. private class ForkedTransition  
  137. {  
  138. private ExecutionContext executionContext;  
  139. private Transition transition;  
  140. }  
  141. }   

 


在具体应用中需要灵活的根据业务逻辑需要派生所需要的分支。

 

3、DefaultAssignment
进行简单的权限操作,这里面主要是将#{reviewer}值作为actorId进行设置
4、JoinEndForkedTokens结束所有节点

java 代码
 
  1. public class JoinEndForkedTokens implements ActionHandler  
  2. {  
  3.   
  4. public JoinEndForkedTokens()  
  5. {  
  6. }  
  7. /* (non-Javadoc) 
  8. * @see org.jbpm.graph.def.ActionHandler#execute(org.jbpm.graph.exe.ExecutionContext) 
  9. */  
  10. public void execute(ExecutionContext executionContext)  
  11. {  
  12. Token token = executionContext.getToken().getParent();  
  13. Map childTokens = token.getActiveChildren();  
  14. for (Object childToken : childTokens.values())  
  15. {  
  16. cancelToken(executionContext, (Token)childToken);  
  17. }  
  18.   
  19. }  
  20. /** 
  21. * 
  22.  
  23. 取消 token 
  24.  
  25. * 
  26. * @param executionContext 
  27. * @param token 
  28. */  
  29. protected void cancelToken(ExecutionContext executionContext, Token token)  
  30. {  
  31.   
  32. Map childTokens = token.getActiveChildren();  
  33. for (Object childToken : childTokens.values())  
  34. {  
  35. cancelToken(executionContext, (Token)childToken);  
  36. }  
  37.   
  38. if (!token.hasEnded())  
  39. {  
  40. token.end(true);  
  41. }  
  42.   
  43.   
  44. cancelTokenTasks(executionContext, token);  
  45. }  
  46. /** 
  47. * 
  48.  
  49. 结束token关联的任务 
  50.  
  51. * 
  52. * @param executionContext 
  53. * @param token 
  54. */  
  55. protected void cancelTokenTasks(ExecutionContext executionContext, Token token)  
  56. {  
  57. TaskMgmtInstance tms = executionContext.getTaskMgmtInstance();  
  58. Collection tasks = tms.getUnfinishedTasks(token);  
  59. for (Object task : tasks)  
  60. {  
  61. TaskInstance taskInstance = (TaskInstance)task;  
  62. if (taskInstance.isBlocking())  
  63. {  
  64. taskInstance.setBlocking(false);  
  65. }  
  66. if (taskInstance.isSignalling())  
  67. {  
  68. taskInstance.setSignalling(false);  
  69. }  
  70. if (!taskInstance.hasEnded())  
  71. {  
  72. taskInstance.end();  
  73. }  
  74. }  
  75. }  
  76. }   

 


结束所有分支节点任务,流向结束节点。  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值