`
pppppp
  • 浏览: 56207 次
  • 来自: ...
社区版块
存档分类
最新评论

使用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. }   

 

 


结束所有分支节点任务,流向结束节点。

 

分享到:
评论
4 楼 rebellan 2008-07-18  
太感谢楼主的分享精神了,搞了好久的会签 被楼主点通了,谢谢
3 楼 zhumaohua 2008-02-21  
        
2 楼 llandyl 2007-12-04  
问题已经解决。是测试程序测试方法不对造成的。
1 楼 llandyl 2007-12-03  
如果将流程定义文件修改,变成两次调用生成<node name="foreachf">就会有错误,而不是直接结束。
错误出现在 executionContext.getJbpmContext().getSession().save(loopToken);  
。通过跟踪发现,是executionContext.getJbpmContext()为空。即报Caused by: java.lang.NullPointerException的错误。
这个问题困扰我几天了。一致没有解决。
不知那位有过此情况下的情况,望告知。谢谢!

相关推荐

    JBPM4.4会签实例

    内含jbpm4.4的会签实例,使用customactivity实现,并且内含有使用的丰富工具类,有兴趣的朋友下载学习~

    jbpm4.3 会签的实现

    会签源文件 博文链接:https://yy666.iteye.com/blog/660701

    jBPM4.4 会签,用custom实现(带加签、减签功能)

    jBPM4.4 会签(带加签、减签功能),通过查找资料,个人摸索,利用custom节点实现了会签功能,加签、减签功能是我自己摸索出来的,是不是能满足大家的需求,仅供参考。

    jbpm-3_2_2-Api

    jbpm-3_2_2-Api jbpm 著名工作流引擎

    jBPM4.4 会签(带加签、减签功能)

    jBPM4.4 会签(带加签、减签功能),通过查找资料,个人摸索,利用task节点实现了会签功能,加签、减签功能是我自己摸索出来的,是不是能满足大家的需求,仅供参考。

    jbpm工作流(会签,串签)

    jbpm的流程部署 流程开始 任务提交 查询已办,待办

    JBPM4工作流应用开始指南.rar

    BPM4工作流应用开发指南 《jBPM4工作流应用开发指南》是2010...306 第20章 中国特色工作流的jBPM实现 307 20.1 退回 308 20.2 取回 313 20.3 会签 318 20.4 委派 326 20.5 自由流 331 20.6 小结 332 附录A jBPM术语 334

    基于JBPM 的特殊工作流研究与实现

    在开源工作流JBPM 的基础上,利用其特有的事件处理机制,提出了实现任务 回退,任务催办和会签任务等特殊工作流的方法,提高了开发效率并具有良好的灵活性,满 足了实际项目开发的需要。

    jbpm4.4学习笔记

    21 会签 53 Xml: 53 code: 54 工作流相关资料 56 22.通过processID查询流程任务 56 23.通过ExecutionId得到 56 24 查询已经结束的流程的节点 56 25 并行任务特点 57 26 得到正在执行的节点 57 27 任务委派给指定人或...

    深入浅出jBPM完整版part1

    1 章 helloworld..............................................2 1.1 下载开发套件.............................................2 1.2 安装流程设计器 .........................................7 1.3 jBPM版...

    工作流开发会签两套方案(Java源代码实现)

    工作流开发会签两套方案(Java源代码实现)

    深入浅出jBPM完整版part2

    1 章 helloworld..............................................2 1.1 下载开发套件.............................................2 1.2 安装流程设计器 .........................................7 1.3 jBPM版...

    基于jbpm与activiti的工作流平台技术架构介绍

    宏天BPM X3软件平台是一个易于部署和使用的新一代业务流程管理平台,能够以最快的速度帮助您梳理、设计、执行、监控分析和优化业务流程,从业务和IT相结合的完美视角为用户组建长期而久远的卓越BPM流程管 理架构。...

    工作流系统源码,5人Team1年的心血结晶

    流程支持会签、并签、自由指派、自由回退、取回、代理等,并在每个审批节点都可以植入Java代码,实现任何业务需求,提供多种报表实时监控。 技术实现非常适合与研究GWT的人,有GWT的自定义控件、GWT与Spring集成、...

Global site tag (gtag.js) - Google Analytics