Jbpm4常用操作

 

Jbpm4 常用操作
 
    一、 ProcessEngine :流程引擎。是 JBPM 上层类,相当于 Hibernate SessionFactory 级别。
    // 获得方式:
    ProcessEngine processEngine = Configuration.getProcessEngine();
       /*Configuration 类会读取 classpath 下的 jbpm.cfg.xml 文件进行流程引擎的加载。 ProcessEngine 是单例模式,即整个系统只会有一个 processEngine 实例。 */
           
 
    二、流程定义
    1. 部署流程定义
       ProcessEngine processEngine = Configuration.getProcessEngine();
       RepositoryService repositoryService = processEngine .getRepositoryService();
    
    例:布署文件中的流程
       // 布署当前目录下 pd.jpdl.xml 文件
       String deploymentId = repositoryService.createDeployment()
                             .addResourceFromClasspath( "process.jpdl.xml" ).deploy();
       /* deploymentId 是发布的流程返回的 ID */
 
 
    2. 删除流程定义
       ProcessDefinition 包含如下属性:
           ID :流程定义 ID
           DeploymentId :流程定义的布署 ID
           Key :关键字
           name :流程名
           version :版本号
     
       数据如下
           ID          Key       名称       版本
           hello-1     hello     hello     1
 
       // 获取类 ProcessDefinition 的属性 ID
       String deploymentId = request.getParameter( "deploymentId" );
       // 根据流程 ID 获取流程定义实例
       ProcessDefinition pd = repositoryService .createProcessDefinitionQuery()
                              .processDefinitionId( deploymentId ).uniqueResult();
       // 根据流程定义的布署 ID 号,删除该流程定义(根据流程定义的 ID 号级联删除)
       // 注意 :jbpm4 是不允许直接根据流程定义的 ID 来直接删除流程定义的,因为还要删除其它配置数据
       repositoryService.deleteDeploymentCascade(pd.getDeploymentId());
 
    3. 获取全部流程定义
      根据流程名获取所有流程定义
       List<ProcessDefinition> processDefinitions = repositoryService
        .createProcessDefinitionQuery().orderAsc( ProcessDefinitionQuery.PROPERTY_NAME).list();
 
    // 还可以根据以下顺序进行排序 (org.jbpm.api.ProcessDefinitionQuery)
    public static final java.lang.String     PROPERTY_DEPLOYMENT_TIMESTAMP      "deployment.timestamp"
    public static final java.lang.String     PROPERTY_ID      "idProperty.stringValue"
    public static final java.lang.String     PROPERTY_KEY      "keyProperty.stringValue"
    public static final java.lang.String     PROPERTY_NAME      "idProperty.objectName"
    public static final java.lang.String     PROPERTY_VERSION     "versionProperty.longValue"
 
    二、流程实例
 
    1. 启动一个流程实例
    1.1 根据 key 启动流程实例
       // 用户必须为新启动的流程实例分配一个 key 这个 key 是用户执行的时候定义的且唯一。通常在业务流程领域找到这种 key 比如,一个订单 id 或者一个保险单号。
       ProcessInstance processInstance = executionService.startProcessInstanceByKey( "ICL" , "CL92837" );
 
       //key 可以用来创建流程实例的 id 格式为 {process-key}.{execution-id} 所以上面的代码会创建一个 id ICL.CL92837 的流向 execution )。
 
    1.2 根据数据库主键启动流程实例
       // 如果没有提供用户定义的 key ,数据库就会把主键作为 key 这样可以使用如下方式获得 id
       ProcessInstance processInstance =       executionService.startProcessInstanceByKey( "ICL" );
       String pid = processInstance .getId();
       // 最好使用一个用户定义的 key 。提供给一个用户定义的 key 你可以组合流向的 id ,而不是执行一个基于流程变量的搜索 - 那种方式太消耗资源了。
 
    1.3 根据变量启动流程实例
       // 为一个新的流程实例启动时就提供一组对象参数。 将这些参数放在 variables 变量里, 然后可以在流程实例创建和启动时使用。
       Map <String,Object> variables = new HashMap<String,Object>();
       variables.put( "customer" , "John Doe" );
       variables.put( "type" , "Accident" );
       variables.put( "amount" , new Float(763.74));
       ProcessInstance processInstance = executionService.startProcessInstanceByKey( "ICL" , variables);
       //
       //JBPM4.4 支持变量历史
       // 变量可以被标记为作为历史记录保存。这意味着,当流程实例结束, 它的运行阶段的信息被删除,历史细节依然会被保存。
       // 通过公共 API ExecutionService 启用变量的历史功能
       void createVariable(String executionId, String name, Object value, boolean historyEnabled);
       void createVariables(String executionId, Map<String, ?> variables, boolean historyEnabled);
       // 通过变量定义
       <variable name= "declaredVar" type= "string" init-expr= "testing declared variable" history= "true" />
 
    2. 根据流程定义,查看流程实例
       // 根据类 ProcessDefinition 的属性 ID ,查看该流程的所有实例
       String processDefinitionId = request.getParameter( "processDefinitionId" );
       return executionService.createProcessInstanceQuery().processDefinitionId(processDefinitionId).list();
 
    3. 执行实例
       // 根据类 ProcessInstance 的属性 ID( 流程实例 ID) ,执行流程实例
       String processInstanceId = request.getParameter( "processInstanceId" );
       executionService.signalExecutionById(processInstanceId);
 
    . 任务
    // 假设流程定义 4-1 如下:
    <process name= "TaskAssignee" >
       <start>
          <transition to= "review" />
       </start>
       <task name= "review" assignee= "#{order.owner}" >
          <transition to= "work" />
       </task>
       <task name= "review" assignee= "de style=" color: rgb(255, 102, 0); ">johndoede>" >
          <transition to= "wait" />
       </task>
       <state name= "wait" />
    </process>
 
    assignee= "johndoe"
       // 表示任务会被分配给用户 ID "johndoe" 的人。
    assignee= "#{order.owner}"
       // 任务被分配给 #{order.owner} 。表示通过 Order 对的 getOwner() 方法会用来获得用户 id ,该用户负责完成这个任务。
    public class Order implements Serializable {
       String owner;  public Order(String owner) {
          this .owner = owner;
       }
       public String getOwner() {
          return owner;
       }
       public void setOwner(String owner) {
          this .owner = owner;
       }
    }
 
    1. 获取任务列表
    1.1 根据用户 ID 获取任务列表
       List<Task> taskList = taskService.findPersonalTasks( "johndoe" );
 
    1.2 根据任务候选人或候选组获取任务列表
       任务可能被分配给一组用户。 其中的一个用户应该接受这个任务并完成它。
       candidate-groups :一个使用逗号分隔的组 id 列表。 所有组内的用户将会成为这个任务的候选人。
       candidate-users :一个使用逗号分隔的用户 id 列表。 所有的用户将会成为这个任务的候选人。
       例如:
       <task name= "review" candidate-groups= "sales-dept" >
          <transition to= "wait" />
       </task>
       假设: sales-dept 有两个成员: johndoe joesmoe
 
       // 这个任务被创建时,不显示在任何人的个人任务列表中。 下面的任务列表会是空的。
       taskService.getAssignedTasks( "johndoe" );
       taskService.getAssignedTasks( "joesmoe" );
 
       分组任务列表中,用户接口必须只接受对这些任务的 接受 操作。
       taskService.takeTask(task.getDbid(), "johndoe" );
       当一个用户接受了一个任务,这个任务的分配人就会变成当前用户。任务会从所有候选人的分组任务列表中消失,它会出现在用户的已分配列表中。
 
    1.3 在一个列表中显示该某人的所有任务
       包括他的个人任务,候选任务,这时直接用 jbpm4 提供的 api 完成不了该功能要求。于是可以使用以下方式进行扩展:
        /**
             * 取得用户的对应的任务列表
             * @param userId
             * @return
             */
            public List<TaskImpl> getTasksByUserId(String userId){
                AppUser user=(AppUser)getHibernateTemplate().load(AppUser. class , new Long(userId));
                Iterator<AppRole> rolesIt=user.getRoles().iterator();
                StringBuffer groupIds= new StringBuffer();
               int i=0;
               while (rolesIt.hasNext()){
                   if (i>0)groupIds.append( "," );
                   groupIds.append( "'" +rolesIt.next().getRoleId().toString()+ "'" );
               }
               /**
                * select * from `jbpm4_task` task
                   left join jbpm4_participation pt on task.`DBID_`=pt.`TASK_`
                   where task.`ASSIGNEE_`='1' or ( pt.`TYPE_` = 'candidate' and (pt.`USERID_`='1')
                   or pt.`GROUPID_`in ('1'))
                */
               StringBuffer hqlSb= new StringBuffer();
               hqlSb.append( "select task from org.jbpm.pvm.internal.task.TaskImpl task left join task.participations pt where task.assignee=?" );
               hqlSb.append( " or (pt.type = 'candidate' and ((pt.userId=?)" );
               
               if (user.getRoles().size()>0){
                   hqlSb.append( " or (pt.groupId in (" +groupIds.toString()+ "))" );
               }
               hqlSb.append( "))" );
               hqlSb.append( " order by task.priority desc" );
       
               return findByHql(hqlSb.toString(), new Object[]{userId,userId});
               
           }
 
    2 分配任务
       如果在流程定义文件中将任务指定到了个人,则 jbpm 自动分配给个人。否则需要进行指定
    2.1 给用户组的用户分配任务
    流程定义文件
       <task name= "review" candidate-groups= "sales-dept" >
          <transition to= "wait" />
       </task>
       假设: sales-dept 有两个成员: johndoe joesmoe
 
       分组任务列表中,用户接口必须只接受对这些任务的 接受 操作。
       taskService.takeTask(task.getDbid(), "johndoe" );
       当一个用户接受了一个任务,这个任务的分配人就会变成当前用户。任务会从所有候选人的分组任务列表中消失,它会出现在用户的已分配列表中。
 
    2.2 任务分配处理器分配任务
       一个 AssignmentHandler 可以通过编程方式来计算 一个任务的分配人和候选人
       public interface AssignmentHandler extends Serializable { 
          void assign(Assignable assignable, OpenExecution execution) throws Exception;
       }
       Assignable 是任务和泳道的通用接口。 所以任务分配处理器可以使用在任务, 也可以用在泳道中。
 
    包含任务分配处理器的流程定义 4-2 如下:
    <process name= "TaskAssignmentHandler" xmlns= "http://jbpm.org/4.2/jpdl" >
       <start g= "20,20,48,48" >
          <transition to= "review" />
       </start>
       <task name= "review" g= "96,16,127,52" >
          <assignment-handler class = "org.jbpm.examples.task.assignmenthandler.AssignTask" >
             <field name= "assignee" >
                <string value= "johndoe" />
             </field>
          </assignment-handler>
          <transition to= "wait" />
      </task>
      <state name= "wait" g= "255,16,88,52" />
    </process>
 
    AssignTask 代码如下
    public class AssignTask implements AssignmentHandler {
       String assignee ;
       public void assign(Assignable assignable, OpenExecution execution) {
          assignable.setAssignee( assignee );
       }
    }
       请注意,默认 AssignmentHandler 实现可以使用使用流程变量,任何其他 Java API 可以访问资源 ,像你的应用数据库来计算分配人和候选人用户和组。
       启动一个 TaskAssignmentHandler 的新流程实例 , 会立即让新流程实例运行到任务节点。 一个新 review 任务被创建,在这个时候 AssignTask 的分配处理器被调用 。这将设置 johndoe 为分配人。 所以 John Doe 将在他自己的任务列表中找到这个任务
 
    2.3 给泳道分配任务
    任务泳道如下面的流程文件 4 -3
    <process name= "TaskSwimlane" xmlns= "http://jbpm.org/4.2/jpdl" >
      <swimlane name= "sales representative" candidate-groups= "sales-dept" />
      <start>
        <transition to= "enter order data" />
      </start>
      <task name= "enter order data" swimlane= "sales representative" >
        <transition to= "calculate quote" />
      </task>
      <task name= "calculate quote" swimlane= "sales representative" >
      </task>
    </process>
 
    在这个例子中,我们在身份组件中 创建了下面的信息
       identityService.createGroup( "sales-dept" );
       identityService.createUser( "johndoe" , "johndoe" , "John" , "Doe" );
       identityService.createMembership( "johndoe" , "sales-dept" );
 
       在启动一个新流程实例后,用户 johndoe 将成为 enter order data 的一个候选人 。还是像上一个流程候选人例子一样, John Doe 可以像这样接收任务
       taskService.takeTask(task.getDbid(), "johndoe" );
 
       接收这个任务将让 johndoe 成为任务的负责人。 直到任务与泳道 sales representative 关联 分配人 johndoe 也会关联到泳道中作为负责人。接下来, John Doe 可以像下面这样完成任务
       taskService.completeTask(taskDbid);
 

       完成任务会将流程执行到下一个任务,下一个任务是calculate quote这个任务也关联着泳道。因此,任务会分配给johndoe

你可能感兴趣的:(职场,休闲,Jbpm4常用操作)