JBPM4工作流应用(二)

 5.task人工任务活动
   1)、使用task活动的assignee属性进行任务分配

 

 

<task name="review" assignee="#{order.owner}"> 
<transition to="wait" /> 
</task>

 

   Assignee属性默认会被作为EL表达式来执行,任务被分配给#{order.owner}。

  

Map<String, Object> variables = new HashMap<String, Object>(); 
variables.put("order", new Order("johndoe")); 
//当一个新流程实例会被创建, 把order 作为一个流程变量分配给它 
ProcessInstance processInstance = executionService 
.startProcessInstanceByKey("TaskAssignee", variables); 
//获取johndoe的任务列表 
List<Task> taskList = taskService.findPersonalTasks("johndoe"); 

 

   2)任务侯选者(candidate-groups,candidate-users)
      candidate-groups:一个使用逗号分隔的组id 列表,所有组内的用户将会成为这个任务的 候选人。
      candidate-users: 一个使用逗号分隔的用户id 列表,所有的用户将会成为这个任务的候选人。

 

<task name="review" candidate-groups="sales-dept> 
<transition to="wait" />
 </task>

 

   部分事例代码如下:

 

// 创建sales-dept组 
dept = identityService.createGroup("sales-dept"); 
// 创建用户johndoe,并加入sales-dept组
 identityService.createUser("johndoe", "John", "Doe"); 
identityService.createMembership("johndoe", dept, "developer");
 // 创建用户joesmoe,并加入sales-dept组 
identityService.createUser("joesmoe", "Joe", "Smoe"); 
identityService.createMembership("joesmoe", dept, "developer"); 
//在流程创建后, 任务会出现在johndoe 和joesmoe 用户的分组任务列表中 
List<Task> taskList = taskService.findGroupTasks("joesmoe"); 
List<Task> taskList = taskService.findGroupTasks("johndoe"); 
//候选人在处理任务之前,必须先接受任务,接受任务后,就会由任务的候选者变成 
// 任务的分配者。同时,此任务会从所有候选者的任务列表中消失。 
taskService.takeTask(task.getId(), "johndoe");

 

 

   3)任务分配处理器(AssignmentHandler)

 

<task name="review">
 <!--assignment-handler 是任务元素的一个子元素,它指定用户代码对象 --> 
<assignment-handler 
class="org.jbpm.examples.task.assignmenthandler.AssignTask"> 
<field name="assignee"> 
<string value="johndoe" /> 
</field> 
</assignment-handler> 
<transition to="wait" /> 
</task>

 

   AssignTask类必须实现AssignmentHandler类,代码如下:

  

//默认AssignmentHandler 实现可以使用使用流程变量 
public class AssignTask implements AssignmentHandler { 
     String assignee;
     public void assign(Assignable assignable, OpenExecution execution) { 
       assignable.setAssignee(assignee);
     }
 }

  

   4)任务泳道(Swimlanes)
     泳道可以理解为流程定义的”全局用户组”,也可以被当作一个流程规则。流程定义中的多个任务需要被分配或候选给
      同一个群用户,统一将这个“同一群用户”定义为“一个泳道”。

 

<!—-在这里定义泳道,属全局用户组--> 
<swimlane name="sales representative" candidate-groups="sales-dept" /> 
<!-- swimlane 引用一个定义在流程中的泳道 --> 
<task name="enter order data" swimlane="sales representative"> 
<transition to="calculate quote"/>
 </task> 
<task name="calculate quote" swimlane="sales representative"> 
</task>

 

 

   泳道中的用户组中的用户在接受任务后成为任务的分配者,同时泳道也会发生变化,接收任务者在流程实例中会被固化为分配者。

taskService.takeTask(taskId, "johndoe");
 assertEquals(0, taskService.findGroupTasks("johndoe").size()); 
taskList = taskService.findPersonalTasks("johndoe"); 
assertEquals(1, taskList.size()); 

  

6.子流程活动(sub-process)


   1)父子流程间的数据交换(parameter-in,parameter-out)
       父流程SubProcessDocument定义JPDL:

<process name="SubProcessDocument" xmlns="http://jbpm.org/4.4/jpdl"> 
<start> 
<transition to="review" /> 
</start> 
<sub-process name="review" sub-process-key="SubProcessReview"> 
<parameter-in var="document" subvar="document" /> 
<parameter-out var="reviewResult" subvar="result" /> 
<transition to="wait" />
 </sub-process> 
<state name="wait"/> 
</process>

 

    子流程SubProcessReview定义JPDL:

<process name="SubProcessReview" xmlns="http://jbpm.org/4.4/jpdl"> 
<start>
 <transition to="get approval"/> 
</start>
 <task name="get approval" assignee="johndoe"> 
<transition to="end"/>
 </task> 
<end name="end"/> 
</process>
 

   流程变量是父子流程用来沟通的纽带。父流程在子流程启动时将自己的“父流程变量”输入子流程,
   反之,子流程在结束时可以将自己的“子流程变量”返回父流程,从而实现父子流程间的数据交换。
    部分事例代码如下:

// 分别部署子流程跟父流程 
String subProcessReviewDeploymentId = repositoryService.createDeployment() 
.addResourceFromClasspath("org/jbpm/examples/subprocess/variables/SubProcessReview.jpdl.xml")
 .deploy(); 
String subProcessDocumentDeploymentId = repositoryService.createDeployment() 
.addResourceFromClasspath("org/jbpm/examples/subprocess/variables/SubProcessDocument.jpdl.xml") 
.deploy(); 
Map<String, Object> variables = new HashMap<String, Object>(); 
variables.put("document", "This document describes how we can make more money..."); 
//设置父流程的变量document ProcessInstance processInstance = executionService
 .startProcessInstanceByKey("SubProcessDocument", variables); 
List<Task> taskList = taskService.findPersonalTasks("johndoe"); Task task = taskList.get(0);
 // 父流程的变量document会被传入子流程,此处为获取子流程的变量document 
String document = (String) taskService
.getVariable(task.getId(), "document"); 
variables = new HashMap<String, Object>(); 
variables.put("result", "accept"); 
// 在子流程中设置流程变量result,该流程变量可在父流程中获取 taskService.setVariables(task.getId(), variables);
 taskService.completeTask(task.getId());
 processInstance = executionService.findProcessInstanceById(processInstance.getId()); 
// 在父流程中获取子流程中设置的流程变量result,名称为reviewResult 
String result = (String) executionService
.getVariable(processInstance.getId(), "reviewResult"); 
assertEquals("accept", result);


 

 

   2)通过outcome属性影响父流程的流程转移
      父流程SubProcessReview定义:

JBPM4工作流应用(二)

 

<!--父流程中的outcome属性引用名称为result的子流程变量
 <sub-process name="review" sub-process-key="SubProcessReview" outcome="#{result}">
 <!—如果result值等于ok,则流向此转移--> 
<transition name="ok" to="next step" /> 
<transition name="nok" to="update" /> 
<transition name="reject" to="close" /> 
</sub-process>

 

   子流程SubProcessReview定义:

<start> 
<transition to="get approval"/>
 </start> 
<task name="get approval" assignee="johndoe"> 
<transition to="end"/> 
</task> 
<end name="end" />

 

   部分事例代码如下:

ProcessInstance processInstance = executionService 
.startProcessInstanceByKey("SubProcessDocument");
 List<Task> taskList = taskService.findPersonalTasks("johndoe"); 
Task task = taskList.get(0);
 Map<String, Object> variables = new HashMap<String, Object>(); 
variables.put("result", "ok");
 // 在子流程中设置流程变量result值为ok,这个ok值会被传递给outcome属性以决定父流程的走向。 
taskService.setVariables(task.getId(), variables); 
taskService.completeTask(task.getId()); 
processInstance = executionService.findProcessInstanceById
(processInstance.getId()); 
assertNotNull(processInstance.findActiveExecutionIn("next step")); 

 

    3)设置不同的子流程end活动名称自动关联父流程的流出转移

      父流程SubProcessReview定义:

<sub-process name="review" sub-process-key="SubProcessReview"> 
<transition name="ok" to="next step" /> 
<transition name="nok" to="update" /> 
<transition name="reject" to="close" /> 
</sub-process> <state name="next step" /> 
<state name="update" /> 
<state name="close" /> 

 

   子流程SubProcessReview定义:

<task assignee="johndoe" name="get approval">
 <transition name="ok" to="ok"/> 
<transition name="nok" to="nok"/>
 <transition name="reject" to="state1"/>
 </task>
 <end name="ok"/> 
<end name="nok"/> 
<end name="reject"/>
 <state name="state1" >
 <transition name="to reject" to="reject"/> 
</state>

 

    部分事例代码如下:

ProcessInstance processInstance = executionService 
.startProcessInstanceByKey("SubProcessDocument");
 List<Task> taskList = taskService.findPersonalTasks("johndoe"); 
Task task = taskList.get(0); 
//子流程活动结束于ok活动返回父流程实例,父流程会自动地通过名称为ok的转移, 
//进入"next step活动" taskService.completeTask(task.getId(), "ok"); 
processInstance = executionService
.findProcessInstanceById(processInstance.getId()); 
assertNotNull(processInstance.findActiveExecutionIn("next step")); 

 

 

7.自定义活动
   如果有特殊而复杂的业务需求,与其生套JBPM本身提供的流转控制活动,不如自己实现一个自定义的活动使用。
Jpdl定义:

 

<!-- custom调用用户代码,实现一个自定义的活动行为 -->
 <custom name="print dots" class="org.jbpm.examples.custom.PrintDots""> 
<transition to="end" /> 
</custom>

 

 自定义活动的类需实现ExternalActivityBehaviour接口

public class PrintDots implements ExternalActivityBehaviour { 
// 在流程实例进入到此活动时执行此方法 
public void execute(ActivityExecution execution) { 
// 执行自定义的处理逻辑 
// 使流程陷入“等待”状态 
execution.waitForSignal();
 }
 // 在流程实例得到执行信号离开此活动时执行此方法
 public void signal(ActivityExecution execution, String signalName,   Map<String, ?> parameters)
 { // 使流程实例进入下一步 
execution.take(signalName);
 } 
}

 

 

8.自动活动
   自动活动是在执行过程中完全无须人工干预地编排好程序,jbpm在处理和执行这些自动活动时能把人工活动产生的数据
   通过流程变量等方式与之完美结合。
  1)java程序活动
  jpdl定义:

<!-- java 任务,流程处理的流向会执行 这个活动配置的方法
 class:完全类名 
method:调用的方法名 
var:返回值存储的 变量名 --> 
<java name="greet" class="org.jbpm.examples.java.JohnDoe" 
method="hello" var="answer" g="96,16,83,52"> 
<!--fileld:在方法调用之前给成员变量注入 配置值 --> 
<field name="state">
<string value="fine"/>
</field>
 <!--arg:方法参数 --> 
<arg><string value="Hi, how are you?"/></arg> 
<transition to="shake hand" /> 
</java>
 <!--expr:这个表达式返回方法被调用 产生的目标对象 ,通过对象参数传入(new Hand()-->
 <java name="shake hand" expr="#{hand}" 
method="shake" var="hand" g="215,17,99,52"> 
<!-- 通过表达式引用流程变量,为shake方法提供2个参数 --> 
<arg><object expr="#{joesmoe.handshakes.force}"/></arg> 
<arg><object expr="#{joesmoe.handshakes.duration}"/></arg> 
<transition to="wait" /> </java>

 

 JohnDoe事例代码如下:

public class JohnDoe implements Serializable {  
  String state;  
  public String hello(String msg) {
    if ( (msg.indexOf("how are you?")!=-1)
       ) {
      return "I'm "+state+", thank you.";
    }
    return null;
  }
}

 

 

 Hand事例代码如下:

public class Hand implements Serializable {
  private boolean isShaken;
  public Hand shake(Integer force, Integer duration) {
    if (force>3 && duration>7) {
      isShaken = true;
    }    
    return this;
  }
  public boolean isShaken() {
    return isShaken;
  }
}

 

 JoeSmoe事例代码如下:

public class JoeSmoe implements Serializable {
  public Map<String, Integer> getHandshakes() {
    Map<String, Integer> handshakes = new HashMap<String, Integer>();
    handshakes.put("force", 5);
    handshakes.put("duration", 12);
    return handshakes;
  }
}

  测试代码如下:

 

Map<String, Object> variables = new HashMap<String, Object>();
    variables.put("hand", new Hand());
    variables.put("joesmoe", new JoeSmoe());
    
    ProcessInstance processInstance = executionService.startProcessInstanceByKey("Java", variables);
    String pid = processInstance.getId();
    
    // 获取流程变量answer
    String answer = (String) executionService.getVariable(pid, "answer");
    assertEquals("I'm fine, thank you.", answer);
    // 获取流程变量hand
    Hand hand = (Hand) executionService.getVariable(pid, "hand");
assertTrue(hand.isShaken());

  

你可能感兴趣的:(jbpm4)