jBPM项目总结

来源:互联网 发布:淘宝怎么没有换货申请 编辑:程序博客网 时间:2024/05/02 06:13
★使用jbpm提供的eclipse plugin在画流程图的时候, 一般的步骤是先画各种节点(我画流程图的顺序是这样的:start node, end node, task node, common node....),然后保存关闭,再打开继续添加transition,因为插件设计器有一个缺点就是第一次就画好transition之后再打开会"惨不忍睹", 各种node会摆放的乱七八糟.

★一般我们认为未命名的那个transtion是默认要执行的transtion,其实不是这样的,通过看源代码:
Java代码 复制代码
  1. public Transition getDefaultLeavingTransition() {   
  2.     Transition defaultTransition = null;   
  3.     if ( (leavingTransitions!=null)   
  4.          && (leavingTransitions.size()>0) ) {   
  5.       defaultTransition = (Transition) leavingTransitions.get(O);   
  6.     } else if ( superState!=null ){   
  7.       defaultTransition = superState.getDefaultLeavingTransition();   
  8.     }   
  9.     return defaultTransition;   
  10.   }  

我们可以看出,实际上第一个transtion才是默认的transition,所以在画流程图的时候要注意这一点,为了让未命名的transtion作为默认的transtion,必须将其放在第一个.

★jbpm数据表结构分析
不管是task变量还是process变量,都保存在jbpm_variableinstance表中,从该表中我们可以看出, 只能存取byte, date, double, long和string这几种类型的变量,所以如果你设置的变量类型为int类型,那么实际上取出来的是long类型的,所以在使用getVariable()方法要取得int类型变量,注意要造型为long.

★不管是task变量还是process变量, 如果要取变量值, 有两种方式, 一种是通过中间表jbpm_tokenvariablemap和jbpm_moduleinstance, jbpm使用hibernate就是通过该方式来取得的, 另一种是通过jbpm_variableinstance表的processinstantce_字段来取得, 一般如果我们手工来获取的话,可以通过该字段来取得.

★ContextInstance实例对应的表是jbpm_moduleinstance,ProcessInstance实例对应的表是jbpm_processintance

★进入子流程之前的事件是subprocess-created而不时node-enter

★token类是一个非常底层的东东,在实际的工作流中很少用到,而用到最多的就是task node以及附加在各个节点上的action handler, 因为只有task node才是人能参与流程的地方, 而jBPM工作流的主要任务就是通过人的操作来让流程运行, 如果在很多地方使用token,那说明你的流程不是人在操作,而是机器在操作.所以大部分我看到的使用token的地方都是在测试中,因为需要通过代码来让流程自动运行.

★state node会将当前的流程挂起,这跟org.jbpm.graph.node.State类有关:
Java代码 复制代码
  1. public class State extends Node {   
  2.      
  3.   private static final long serialVersionUID = 1L;   
  4.   
  5.   public State() {   
  6.     this(null);   
  7.   }   
  8.      
  9.   public State(String name) {   
  10.     super( name );   
  11.   }   
  12.   
  13.   public void execute(ExecutionContext executionContext) {   
  14.   }   
  15. }  

因为它的execute()方法为空, 而其他的节点的execute方法中都会调用leave()方法继续流程的执行,跑到下一个节点,也别指望在state node中通过ProcessInstance.signal()方法来启动流程,因为没有地方提供你放该执行代码,即使通过在event的actionhandler中来让流程继续执行也不行,因为在执行execute方法之前有一个流程锁定的动作,而在execute方法执行之后则有一个解锁的处理,而位于action中execute方法中的signal方法也会检查当前节点是否锁定,因为在执行execute方法之前已经锁定所以会抛出node被锁定的异常.而要让流程继续执行需要在流程之外通过调用ProcessInstance.signal()方法让流程继续执行.

★一般流程图的画法, 一般按照流程的顺序遵循从上到下,从左到右的原则
★申请界面可能千差万别,但是审核页面都基本类似:审核内容,审核历史,审核意见, 所以我做成了通用的页面

★为了将业务表单数据挂到jBPM流程引擎上,一般需要使用一个全局的流程实例变量(我一般采用FORM_ID)将指定的业务表单记录主键保存,这样在流程中的不同节点就可以取得所需要的业务数据,并交给不同的操作对象(Actor)进行处理.

★为了使用指定的页面来处理每个流程任务节点,需要将页面的url保存为任务节点变量, 这样就将jsp页面跟jBPM流程的任务节点联系起来了.而这个工作是放在AssignmentHandler中来处理的.在本人的项目中这是一个通用的做法,所以写了一个AssignmentHandler抽象类:
Java代码 复制代码
  1. /**  
  2.  * 审核任务节点对应的分配处理handler 主要设置处理当前审核任务的actor和审核操作页面, 默认的审核页面不能对审核内容进行编辑  
  3.  *   
  4.  * @author Macro Chen  
  5.  * @since Apr 18, 2008  
  6.  */  
  7. public abstract class BaseAssignmentHandler implements AssignmentHandler {   
  8.   
  9.     public void assign(Assignable assignable, ExecutionContext ctx)   
  10.             throws Exception {   
  11.         addContextInstanceVariables(ctx.getContextInstance());   
  12.         String employeeId = getActorId(assignable, ctx);   
  13.         assignable.setActorId(employeeId);   
  14.         addTaskInstanceVariables(assignable, ctx);   
  15.     }   
  16.   
  17.     /**  
  18.      * 添加task instance变量  
  19.      *   
  20.      * @param assignable  
  21.      * @param ctx  
  22.      */  
  23.     protected void addTaskInstanceVariables(Assignable assignable,   
  24.             ExecutionContext ctx) {   
  25.         TaskInstance ti = (TaskInstance) assignable;   
  26.         String url = getOperationUrl(assignable, ctx);   
  27.         url += (url.indexOf("?") != -1 ? "&" : "?") + "taskId=" + ti.getId();   
  28.         ti.setVariable(JbpmConstants.TIV_OPERATION_URL, url);   
  29.     }   
  30.   
  31.     /**  
  32.      * 根据业务需要添加其他的流程变量  
  33.      *   
  34.      * @param ci  
  35.      */  
  36.     protected void addContextInstanceVariables(ContextInstance ci) {   
  37.     }   
  38.   
  39.     /**  
  40.      * 执行任务操作的页面 默认情况下使用通用的审核页面(不可对审核内容进行修改), 子类可以根据需要开发自己的审核页面(如可对审核内容进行修改)  
  41.      *   
  42.      * @return  
  43.      */  
  44.     protected String getOperationUrl(Assignable assignable, ExecutionContext ctx) {   
  45.         return "/workflow/common/common_audit.jsp";   
  46.     }   
  47.   
  48.     /**  
  49.      * 设置当前任务节点的执行者  
  50.      *   
  51.      * @param assignable  
  52.      * @param ctx  
  53.      * @return  
  54.      * @throws Exception  
  55.      */  
  56.     protected abstract String getActorId(Assignable assignable,   
  57.             ExecutionContext ctx) throws Exception;   
  58.   
  59. }  


★以下是本人总结的一些公共的,方便的jBPM静态方法,在整个项目中通用:
Java代码 复制代码
  1. /**  
  2.  * @author Macro Chen  
  3.  * @since Apr 8, 2008  
  4.  */  
  5. public class JbpmUtils {   
  6.   
  7.     public static Long getLongVariableOfProcess(IJbpmProvider provider,   
  8.             String name) {   
  9.         ContextInstance ci = provider.getContextInstance();   
  10.         if (ci == null) {   
  11.             return (long)0;   
  12.         }   
  13.         return (Long)ci.getVariable(name);   
  14.     }   
  15.   
  16.     public static JbpmContext getJbpmContext() {   
  17.         JbpmConfiguration config = JbpmConfiguration.getInstance();   
  18.         return config.getCurrentJbpmContext();   
  19.     }   
  20.   
  21.     /**  
  22.      * 新建一个pi  
  23.      *   
  24.      * @param name  
  25.      * @return  
  26.      */  
  27.     public static ProcessInstance newProcessInstance(String name) {   
  28.         ProcessDefinition pd = getJbpmContext().getGraphSession()   
  29.                 .findLatestProcessDefinition(name);   
  30.         return new ProcessInstance(pd);   
  31.     }   
  32.   
  33.     /**  
  34.      * 根据taskId取得pi  
  35.      *   
  36.      * @param taskId  
  37.      * @return  
  38.      */  
  39.     public static ProcessInstance getProcessInstanceByTaskId(String taskId) {   
  40.         TaskInstance ti = getTaskInstance(taskId);   
  41.         return ti.getTaskMgmtInstance().getProcessInstance();   
  42.     }   
  43.   
  44.     public static ProcessInstance getProcessInstanceByTaskId(Long taskId) {   
  45.         TaskInstance ti = getTaskInstance(taskId);   
  46.         return ti.getTaskMgmtInstance().getProcessInstance();   
  47.     }   
  48.   
  49.     public static ContextInstance getContextInstance(String name) {   
  50.         return newProcessInstance(name).getContextInstance();   
  51.     }   
  52.   
  53.     public static ContextInstance getContextInstanceByTaskId(String taskId) {   
  54.         TaskInstance ti = getTaskInstance(taskId);   
  55.         if (ti == null)   
  56.             return null;   
  57.   
  58.         return ti.getTaskMgmtInstance().getProcessInstance()   
  59.                 .getContextInstance();   
  60.     }   
  61.   
  62.     public static ContextInstance getContextInstanceByTaskId(Long taskId) {   
  63.         TaskInstance ti = getTaskInstance(taskId);   
  64.         if (ti == null)   
  65.             return null;   
  66.         return ti.getTaskMgmtInstance().getProcessInstance()   
  67.                 .getContextInstance();   
  68.     }   
  69.   
  70.     public static TaskInstance createStartTaskInstance(ProcessInstance pi) {   
  71.         return pi.getTaskMgmtInstance().createStartTaskInstance();   
  72.     }   
  73.   
  74.     public static Session getSession() {   
  75.         return getJbpmContext().getSessionFactory().openSession();   
  76.     }   
  77.   
  78.     public static List getQueryList(String hql) {   
  79.         return getSession().createQuery(hql).list();   
  80.     }   
  81.   
  82.     public static TaskMgmtSession getTaskMgmt() {   
  83.         return getJbpmContext().getTaskMgmtSession();   
  84.     }   
  85.   
  86.     public static TaskInstance loadTaskInstance(long taskId) {   
  87.         return getTaskMgmt().loadTaskInstance(taskId);   
  88.     }   
  89.   
  90.     public static TaskInstance getTaskInstance(String taskId) {   
  91.         if (StringUtils.isEmpty(taskId))   
  92.             return null;   
  93.         return getJbpmContext().getTaskInstance(Long.parseLong(taskId));   
  94.     }   
  95.   
  96.     public static TaskInstance getTaskInstance(long taskId) {   
  97.         return getJbpmContext().getTaskInstance(taskId);   
  98.     }   
  99.   
  100.     public static List<TaskInstance> findTaskInstances(String actorId) {   
  101.         return getTaskMgmt().findTaskInstances(actorId);   
  102.     }   
  103.   
  104.     public static List<TaskInstance> findPooledTaskInstances(String actorId) {   
  105.         return getTaskMgmt().findPooledTaskInstances(actorId);   
  106.     }   
  107.   
  108.     public static void saveTaskInstance(TaskInstance ti) {   
  109.         getJbpmContext().save(ti);   
  110.     }   
  111.   
  112.     public static String getTaskId() {   
  113.         return DoradoUtils.getRequestParameter(JbpmConstants.TASK_ID);   
  114.     }   
  115.   
  116. }  
原创粉丝点击