`
fyjjack
  • 浏览: 33619 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Jbpm4中的会签设计及实现

    博客分类:
  • JBPM
阅读更多

jbpm4.4提供了三种比较方便的分支跳转方式,如下所示:

1.通过expression

 

Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.   
  3. <process name="DecisionExpression" xmlns="http://jbpm.org/4.4/jpdl">   
  4.   
  5.   <start g="16,102,48,48">   
  6.     <transition to="evaluate document"/>   
  7.   </start>   
  8.   
  9.   <decision name="evaluate document" expr="#{content}" g="96,102,48,48">   
  10.     <transition name="good" to="submit document" g="120,60:-36,23" />   
  11.     <transition name="bad"  to="try again" g=":-15,-21" />   
  12.     <transition name="ugly" to="give up" g="120,189:-35,-41" />   
  13.   </decision>   
  14.   
  15.   <state name="submit document" g="175,35,122,52" />   
  16.   <state name="try again" g="176,100,122,52" />   
  17.   <state name="give up" g="177,164,122,52" />   
  18.   
  19. </process>  
<?xml version="1.0" encoding="UTF-8"?>

<process name="DecisionExpression" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="16,102,48,48">
    <transition to="evaluate document"/>
  </start>

  <decision name="evaluate document" expr="#{content}" g="96,102,48,48">
    <transition name="good" to="submit document" g="120,60:-36,23" />
    <transition name="bad"  to="try again" g=":-15,-21" />
    <transition name="ugly" to="give up" g="120,189:-35,-41" />
  </decision>

  <state name="submit document" g="175,35,122,52" />
  <state name="try again" g="176,100,122,52" />
  <state name="give up" g="177,164,122,52" />

</process>
 

2.通过handler

Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.   
  3. <process name="DecisionHandler" xmlns="http://jbpm.org/4.4/jpdl">   
  4.   
  5.   <start g="16,102,48,48">   
  6.     <transition to="evaluate document" name=""/>   
  7.   </start>   
  8.   
  9.   <decision name="evaluate document" g="96,102,48,48">   
  10.     <handler class="org.jbpm.examples.decision.handler.ContentEvaluation"/>   
  11.     <transition name="good" to="submit document" g="120,60:-37,22" />   
  12.     <transition name="bad" to="try again" g=":-19,-22" />   
  13.     <transition name="ugly" to="give up" g="120,189:-33,-39" />   
  14.   </decision>   
  15.   
  16.   <state name="submit document" g="175,35,122,52" />   
  17.   <state name="try again" g="176,100,122,52" />   
  18.   <state name="give up" g="177,164,122,52" />   
  19.   
  20. </process>  
<?xml version="1.0" encoding="UTF-8"?>

<process name="DecisionHandler" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="16,102,48,48">
    <transition to="evaluate document" name=""/>
  </start>

  <decision name="evaluate document" g="96,102,48,48">
    <handler class="org.jbpm.examples.decision.handler.ContentEvaluation"/>
    <transition name="good" to="submit document" g="120,60:-37,22" />
    <transition name="bad" to="try again" g=":-19,-22" />
    <transition name="ugly" to="give up" g="120,189:-33,-39" />
  </decision>

  <state name="submit document" g="175,35,122,52" />
  <state name="try again" g="176,100,122,52" />
  <state name="give up" g="177,164,122,52" />

</process>
 

3.通过condition

Java代码 复制代码 收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.   
  3. <process name="DecisionConditions" xmlns="http://jbpm.org/4.4/jpdl">   
  4.   
  5.   <start g="16,102,48,48">   
  6.     <transition to="evaluate document" />   
  7.   </start>   
  8.   
  9.   <decision name="evaluate document" g="96,102,48,48">   
  10.     <transition to="submit document" g="120,60:">   
  11.       <condition expr="#{content==&quot;good&quot;}" />   
  12.     </transition>   
  13.     <transition to="try again">   
  14.       <condition expr="#{content==&quot;bad&quot;}" />   
  15.     </transition>   
  16.     <transition to="give up" g="120,189:" />   
  17.   </decision>   
  18.   
  19.   <state name="submit document" g="175,35,122,52"/>   
  20.   <state name="try again" g="176,100,122,52"/>   
  21.   <state name="give up" g="177,164,122,52"/>   
  22.   
  23. </process>  
<?xml version="1.0" encoding="UTF-8"?>

<process name="DecisionConditions" xmlns="http://jbpm.org/4.4/jpdl">

  <start g="16,102,48,48">
    <transition to="evaluate document" />
  </start>

  <decision name="evaluate document" g="96,102,48,48">
    <transition to="submit document" g="120,60:">
      <condition expr="#{content==&quot;good&quot;}" />
    </transition>
    <transition to="try again">
      <condition expr="#{content==&quot;bad&quot;}" />
    </transition>
    <transition to="give up" g="120,189:" />
  </decision>

  <state name="submit document" g="175,35,122,52"/>
  <state name="try again" g="176,100,122,52"/>
  <state name="give up" g="177,164,122,52"/>

</process>
 

我们发现这种方式,若一旦我们的流程定义完成后,再想在运行中动态改变这种分支条件的设计就很难了,但是我们知道可以在流程定义发布到后台后,我们可以提供动态修改xml的方式,用handler的方式加上我们的分支决定的decision(需要实现jpbm的decision接口即可),通过handler来实现分支有一个比较大的优点就是我们可以在handler动态去执行我们需要工作流额外执行的代码,并且可以通过这个判断来决定其跳转的路径。

 

但我们不可能为所有的有分支决定的流程都加一个decision handler,并且在里面进行动态的分支判断。那样的工作很大,并且不灵活。

 

我们看一下第二种handler的接口:

Java代码 复制代码 收藏代码
  1. package org.jbpm.examples.decision.handler;   
  2.   
  3. import org.jbpm.api.jpdl.DecisionHandler;   
  4. import org.jbpm.api.model.OpenExecution;   
  5.   
  6. public class ContentEvaluation implements DecisionHandler {   
  7.   
  8.   private static final long serialVersionUID = 1L;   
  9.   
  10.   public String decide(OpenExecution execution) {   
  11.     String content = (String) execution.getVariable("content");   
  12.     if (content.equals("you're great")) {   
  13.       return "good";   
  14.     }   
  15.     if (content.equals("you gotta improve")) {   
  16.       return "bad";   
  17.     }   
  18.     return "ugly";   
  19.   }   
  20. }  
package org.jbpm.examples.decision.handler;

import org.jbpm.api.jpdl.DecisionHandler;
import org.jbpm.api.model.OpenExecution;

public class ContentEvaluation implements DecisionHandler {

  private static final long serialVersionUID = 1L;

  public String decide(OpenExecution execution) {
    String content = (String) execution.getVariable("content");
    if (content.equals("you're great")) {
      return "good";
    }
    if (content.equals("you gotta improve")) {
      return "bad";
    }
    return "ugly";
  }
}

 在这里我们可以看到,可以通过动态返回跳转路径则可。在上面我说过了,不能把这个返回值交给具体的decisionHandler来决定,这个决定应该由流程运行来动态决定,我们需要告诉这个handler,你需要按我的规则来运行计算,得到一个运行跳转的路径。于是我想到能不能用bsh有脚本来动态返回告诉这个handler如何执行。

 

以下我们以一个简单的订单流程来说明如何实现这个动态设计分支跳转。

 

首先我在线设计了一个流程,如下所示:

jbpm4在线流程设计

 

发布后,设计其分支条件,如下所示:

jbpm4分支条件设计

 

我们在条件那里加入流程干预:

Java代码 复制代码 收藏代码
  1. String tranTo="金额小于2000元";   
  2. if(price*quantity>=2000){   
  3.        tranTo="金额大于等于2000";   
  4. }  
String tranTo="金额小于2000元";
if(price*quantity>=2000){
       tranTo="金额大于等于2000";
}

 这个tranTo则是由我们系统的管理员来控制,大家发现其本身就是java代码来的,熟悉一些简单的java语法均可以。当然若我们在这里还可以做一些更复杂的操作,如执行调用第三方系统的接口等。

那么以上的price与quantity变量来自哪里呢?它们是流程表单里的字段,于是我们为这个流程动态绑定一个流程表单。

 

首先我们设计一个流程表单:

在线表单设计

 

其对应的字段映射为:

在线表单设计-表单字段

在后台绑定该表单:

绑定表单

启动流程:

绑定流程表单-启动

执行后,可以看到流程自动判断跳转:

 

我们看一下本身我们的handler如何写:

 

Java代码 复制代码 收藏代码
  1. package com.htsoft.oa.workflow.handler;   
  2.   
  3. import java.util.Iterator;   
  4. import java.util.List;   
  5. import java.util.Map;   
  6. import java.util.Map.Entry;   
  7.   
  8. import org.apache.commons.logging.Log;   
  9. import org.apache.commons.logging.LogFactory;   
  10. import org.jbpm.api.ProcessDefinition;   
  11. import org.jbpm.api.ProcessEngine;   
  12. import org.jbpm.api.jpdl.DecisionHandler;   
  13. import org.jbpm.api.model.Activity;   
  14. import org.jbpm.api.model.OpenExecution;   
  15.   
  16. import bsh.EvalError;   
  17. import bsh.Interpreter;   
  18.   
  19. import com.htsoft.core.util.AppUtil;   
  20. import com.htsoft.oa.model.flow.ProHandleComp;   
  21. import com.htsoft.oa.service.flow.ProHandleCompService;   
  22. /**  
  23.  * 实现分支决定,可以在这里根据业务逻辑计算,决定分支的跳转  
  24.  * @author   
  25.  *  
  26.  */  
  27. public class DecisionHandlerImpl implements DecisionHandler{   
  28.        
  29.     private static final Log logger=LogFactory.getLog(DecisionHandlerImpl.class);   
  30.        
  31.     @Override  
  32.     public String decide(OpenExecution execution) {   
  33.         logger.debug("enter decision handler....");   
  34.            
  35.         ProcessEngine processEngine=(ProcessEngine)AppUtil.getBean("processEngine");   
  36.            
  37.         ProHandleCompService proHandleCompService=(ProHandleCompService)AppUtil.getBean("proHandleCompService");   
  38.            
  39.         String pdId=execution.getProcessDefinitionId();   
  40.            
  41.         ProcessDefinition processDefinition= processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(pdId).uniqueResult();   
  42.            
  43.         String deployId=processDefinition.getDeploymentId();   
  44.            
  45.         Activity curActivity=execution.getActivity();   
  46.            
  47.         List<ProHandleComp> list=proHandleCompService.getByDeployIdActivityNameHandleType(deployId, curActivity.getName(), ProHandleComp.HANDLE_TYPE_HANDLER);   
  48.            
  49.         if(list.size()>0){   
  50.             ProHandleComp proHandleComp=list.get(0);   
  51.             logger.info("exeCode:" + proHandleComp.getExeCode());   
  52.             //执行动态   
  53.             Interpreter it=new Interpreter();   
  54.                    
  55.             try {   
  56.                 //取得所有流程变量,放于bsh环境,方便在bsh脚本环境中运行以方便决定流程跳转   
  57.                 Map<String,Object> vars=(Map<String,Object>)execution.getVariables();   
  58.                 Iterator<Entry<String, Object>> iterator= vars.entrySet().iterator();   
  59.                 while(iterator.hasNext()){   
  60.                     Entry<String, Object> entry=iterator.next();   
  61.                     String key=entry.getKey();   
  62.                     Object val=entry.getValue();   
  63.                     it.set(key.replace(".""_"), val);   
  64.                 }   
  65.                 logger.info("dynamic execution code tranTo:"+proHandleComp.getExeCode());   
  66.                 it.eval(proHandleComp.getExeCode());   
  67.                 String tran=(String)it.get("tranTo");   
  68.                 logger.info("return tranTo:"+tran);   
  69.                 return tran;   
  70.             } catch (EvalError e) {   
  71.                 e.printStackTrace();   
  72.             }   
  73.         }   
  74.            
  75.         return null;   
  76.     }   
  77. }  
package com.htsoft.oa.workflow.handler;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jbpm.api.ProcessDefinition;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.jpdl.DecisionHandler;
import org.jbpm.api.model.Activity;
import org.jbpm.api.model.OpenExecution;

import bsh.EvalError;
import bsh.Interpreter;

import com.htsoft.core.util.AppUtil;
import com.htsoft.oa.model.flow.ProHandleComp;
import com.htsoft.oa.service.flow.ProHandleCompService;
/**
 * 实现分支决定,可以在这里根据业务逻辑计算,决定分支的跳转
 * @author 
 *
 */
public class DecisionHandlerImpl implements DecisionHandler{
	
	private static final Log logger=LogFactory.getLog(DecisionHandlerImpl.class);
	
	@Override
	public String decide(OpenExecution execution) {
		logger.debug("enter decision handler....");
		
		ProcessEngine processEngine=(ProcessEngine)AppUtil.getBean("processEngine");
		
		ProHandleCompService proHandleCompService=(ProHandleCompService)AppUtil.getBean("proHandleCompService");
		
		String pdId=execution.getProcessDefinitionId();
		
		ProcessDefinition processDefinition= processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionId(pdId).uniqueResult();
		
		String deployId=processDefinition.getDeploymentId();
		
		Activity curActivity=execution.getActivity();
		
		List<ProHandleComp> list=proHandleCompService.getByDeployIdActivityNameHandleType(deployId, curActivity.getName(), ProHandleComp.HANDLE_TYPE_HANDLER);
		
		if(list.size()>0){
			ProHandleComp proHandleComp=list.get(0);
			logger.info("exeCode:" + proHandleComp.getExeCode());
			//执行动态
			Interpreter it=new Interpreter();
				
			try {
				//取得所有流程变量,放于bsh环境,方便在bsh脚本环境中运行以方便决定流程跳转
				Map<String,Object> vars=(Map<String,Object>)execution.getVariables();
				Iterator<Entry<String, Object>> iterator= vars.entrySet().iterator();
				while(iterator.hasNext()){
					Entry<String, Object> entry=iterator.next();
					String key=entry.getKey();
					Object val=entry.getValue();
					it.set(key.replace(".", "_"), val);
				}
				logger.info("dynamic execution code tranTo:"+proHandleComp.getExeCode());
				it.eval(proHandleComp.getExeCode());
				String tran=(String)it.get("tranTo");
				logger.info("return tranTo:"+tran);
				return tran;
			} catch (EvalError e) {
				e.printStackTrace();
			}
		}
		
		return null;
	}
}
 

 

里面其实比较简单,就是通过动态执行那个给用户开放的代码片段,并且根据其tranTo变量的值来决定其如何跳转,在上面的例子就是流程表单中的金额是否大于2000元来跳转。

 

同样,我们知道jbpm4_lob中存着jbpm4的流程定义的xml文件,只要把动态修改jbpm4的流程定义,可以为我们的作何节点加上我们需要流程动态执行的事件及代码。请关注后续的文章,有介绍如何扩展jbpm4的流程事件。

 

 

在线看预览情况:

 

http://bbs.jee-soft.cn/swf/design_decision.html

 

http://bbs.jee-soft.cn/posts/list/285.page#384

在线测试地址:

网通:

http://oa.jee-soft.cn:8080/index.jsp

电信:

http://office.jee-soft.cn:8080/index.jsp

 

用户:admin,密码:1

分享到:
评论

相关推荐

    jbpm4.3 会签的实现

    【jbpm4.3 会签的实现】 在企业级工作流管理系统中,会签...在实际项目中,结合测试(如压缩包中的"test"目录中的测试用例)和持续学习(如"sofocus"可能包含的相关文档或讨论),将进一步加深对jbpm会签机制的理解。

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

    在本篇中,我们将深入探讨如何在jBPM4.4中实现自定义会签功能,同时包含加签和减签功能。 首先,我们需要了解什么是会签。会签是指在流程中涉及多个审批人的场景,每个审批人都需要对流程中的某个任务进行操作,...

    JBPM4.4会签实例

    通过学习"CountersignDemo"这个实例,你可以深入了解JBPM4.4的会签实现,包括如何设计流程、创建自定义活动、编写工具类以及如何在实际应用中部署和使用。这将有助于提升你对业务流程管理的理解,使你能更好地为企业...

    JBPM4.3 Spring会签 实例

    在这个实例中,我们将探讨如何在JBPM4.3中实现基于Spring的会签功能。会签是一种常见的业务流程操作,需要多个参与者依次或同时对同一文档或任务进行审批,所有参与者的签名都得到确认后,流程才能继续进行。这通常...

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

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

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

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

    jbpm工作流(会签,串签)

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

    jbpm4案例源码

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

    jbpm会签.zip

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

    jBPM4入门基础环境配置

    - **Eclipse IDE**:推荐使用Eclipse IDE,因为它有jBPM4的插件支持,可以方便地进行流程设计和调试。 ### 3. 下载与导入jBPM4 访问jBPM官方网站或GitHub仓库下载jBPM4的最新发行版。解压后,将`jbpm-installer`...

    huiqian.rar_jbpm4

    在jbpm4中,会签可以通过工作流定义(即流程模型)和工作项处理来实现。 首先,我们需要理解jbpm4的核心组件。jbpm4提供了一个流程建模工具,如jBPM Process Designer,用于创建BPMN 2.0兼容的流程图。这些流程图...

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

    包括jBPM4扩展研发先决条件、深入jPDL和jBPM Service API、升级jBPM3到jBPM4、流程虚拟机原理、jBPM4的设计思想、随需而配jBPM4、异步工作执行器、深入jBPM4电子邮件支持、系统日志、jBPM4与Spring框架集成、jBPM4与...

    jbpm4.4流程图

    流程图的设计完成后,可以编译成jpdl文件,然后在jbpm引擎中部署,以便执行和跟踪。 流程图的每个组成部分都有其特定的意义: 1. **开始事件**:流程的起点,标记流程的启动。 2. **任务**:代表业务操作,可以是...

    jbpm4.4 简单请假流程

    综上,"jbpm4.4简单请假流程"项目展示了如何利用jbpm4.4的特性设计和实现一个典型的业务流程,涵盖了流程定义、任务处理、决策逻辑以及系统集成等方面,为企业级流程管理提供了实用范例。通过对这个项目的理解和实践...

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

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

    JBPM与Activity分析.doc

    JBPM与Activiti作为当前市场上主流的工作流引擎,因其开源特性及强大的功能受到了广泛的关注与应用。本文将对JBPM和Activiti进行深入的分析,并与国内的工作流引擎FixFlow进行对比。 #### 二、JBPM与Activiti对比...

Global site tag (gtag.js) - Google Analytics