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

使用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.3 会签的实现

    本文将深入探讨jbpm4.3如何实现会签功能,并分享相关的源码和工具使用。 1. jbpm4.3概述: jbpm4.3是jbpm的一个较旧版本,但仍然包含许多工作流管理的核心特性,如流程定义、任务分配、事件处理等。它基于Java平台...

    JBPM4.3 Spring会签 实例

    解压并运行这个示例,可以更深入地理解JBPM4.3和Spring如何协同工作以实现会签功能。 总之,这个JBPM4.3与Spring的会签实例展示了如何在企业级应用中有效地管理和控制业务流程。通过学习和实践这样的实例,开发者...

    JBPM4.4会签实例

    在JBPM4.4中,实现会签功能通常需要以下几个步骤: 1. **设计流程模型**:使用BPMN(Business Process Modeling Notation)语言或JBPM提供的图形化工具(如jBPM Designer)设计流程模型,定义会签节点。在这个节点...

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

    在实现会签时,我们可以创建一个custom节点,然后在其中编写Java代码或者使用脚本来处理会签逻辑,包括分配任务给审批人、处理审批结果以及根据需要进行加签或减签操作。 加签功能是在流程运行过程中,根据业务需求...

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

    本文将深入探讨如何在jbPM中实现会签以及加签、减签功能,并提供相关实践指导。 1. **会签概念与实现** 会签是指在流程中设置一个环节,需要多个参与者依次或同时进行审批。jbPM通过定义工作流模型,利用task节点...

    jbpm工作流(会签,串签)

    在本教程中,我们将深入探讨jbpm中的会签和串签功能,以及如何进行流程部署、启动流程、任务提交、查询已办和待办任务。 首先,让我们了解流程部署的概念。在jbpm中,流程部署是将一个流程定义文件(通常是.bpmn或....

    jbpm-3_2_2-Api

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

    jbpm4.4 会签 测试( fork & join)

    在jbpm中,"fork & join"机制是实现并行处理和流程控制的关键概念,尤其在处理会签(多个审批人同时参与审批)等场景时显得尤为重要。 "fork"在jbpm中指的是流程分支,当流程到达一个fork节点时,流程会分裂为多个...

    jbpm会签.zip

    在jbpm中实现会签,主要涉及到以下几个关键知识点: 1. **工作流模型**:jbpm使用BPMN(Business Process Model and Notation)标准来定义流程模型。BPMN提供了一套图形化的符号,用于描绘业务流程,其中包括并行...

    jbpm4案例源码

    在阅读《jBPM4工作流应用开发指南.pdf》这本书时,你可以学习到如何使用jbpm4的API进行流程设计、部署和执行,以及如何进行流程实例的查询和管理。书中可能还会涉及如何处理异常、分支和合并逻辑,以及如何进行流程...

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

    本主题聚焦于"工作流开发会签两套方案(Java源代码实现)",我们将深入探讨两种Java实现会签功能的方法,并结合JBPM(Java Business Process Management)框架,为你揭示如何高效地构建这样的系统。 首先,我们需要...

    jBPM4入门基础环境配置

    使用jBPM4提供的图形化工具(例如,eclipse的jbpm4 designer插件)创建流程定义文件(.bpmn2或.xml)。流程图可以通过拖放活动节点(如开始、结束、任务、会签等)来构建,并通过连接线定义它们之间的流转关系。 ##...

    jbpm工作流程的说明文档

    【jbpm工作流程详解】 jbpm,全称为Java Business Process ...尽管在应对某些特定的中国业务场景时可能需要额外的定制,但通过对其特性和机制的深入理解,开发者可以有效利用jbpm实现符合中国国情的流程自动化。

    JPBM 会签 示例

    给新手学习使用,不会让你失望" 提示我们,该示例项目是为初学者准备的,通过简洁明了的代码和注释,帮助他们快速理解和掌握JBPM如何实现会签功能。这意味着文件内容可能包括了基础的JBPM配置、工作流定义、会签节点...

    jbpm4.4流程图

    3. **网关**:用于控制流程的分支和合并,如并行网关实现任务并行执行,决策网关根据条件决定流程走向。 4. **连接线**:指示流程的流转路径,可能带有条件表达式,决定何时从一个活动转移到另一个。 5. **结束事件*...

    jbpm使用和说明文档v1.1_1.doc

    例如,创建草稿任务、并发任务、会签任务等,这些都是通过控制类在流程图执行过程中动态生成的。 4. **流程监控与调试**:jbpm提供了监控和调试工具,可以帮助开发者跟踪流程实例的执行状态,找出潜在的问题并进行...

    huiqian.rar_jbpm4

    1. **流程定义**:代码可能会定义一个流程实例,其中包含并行网关来实现会签。并行网关将任务分支到不同的参与者,每个参与者完成自己的签署后,所有分支必须汇合,流程才能继续。 2. **任务监听器**:为了跟踪各个...

Global site tag (gtag.js) - Google Analytics