Jbpm4常用操作
一、流程定義?
1.部署流程定義?
?? ProcessEngine processEngine = new Configuration().buildProcessEngine();?
?? RepositoryService repositoryService = processEngine.getRepositoryService();?
??
例:布署文件中的流程?
?? //布署當前目錄下pd.jpdl.xml文件?
?? String deploymentId = repositoryService.createDeployment()?
???????????????????????? .addResourceFromClasspath("pd.jpdl.xml").deploy();?
例:布署網頁上TextArea中的流程?
?? <form action="jbpm?family168=deploy" method="post">?
??????? <textarea name="xml" cols=50 rows=15></textarea>?
??????? <input type="submit" value="發布"/>?
??????? <input type="reset" value="取消"/>?
?? </form>?
?? 在后臺處理如下:?
?? String xml = request.getParameter("xml");?
?? repositoryService.createDeployment()?
??????????????????? .addResourceFromString("process.jpdl.xml", xml).deploy();?
2.刪除流程定義?
?? 類ProcessDefinition 包含如下屬性:?
?????? ID:流程定義ID號?
?????? DeploymentId:流程定義的布署ID號?
?????? Key:關鍵字?
?????? name:流程名?
?????? version:版本號?
???
?? 數據如下?
?????? ID????????? Key?????? 名稱????? 版本?
?????? hello-1???? hello???? hello???? 1?
?? //獲取類ProcessDefinition的屬性ID?
?? String id = request.getParameter("id");?
?? //根據流程ID獲取流程定義實例?
?? ProcessDefinition pd = repositoryService.createProcessDefinitionQuery()?
????????????????????????? .processDefinitionId(id).uniqueResult();?
?? //根據流程定義的布署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);?
?? 參見流程定義4-1,把order作為一個流程變量分配給它,啟動新流程實例代碼如下:?
?? Map<String, Object> variables = new HashMap<String, Object>();?
?? variables.put("order", new Order("johndoe"));?
?? ProcessInstance processInstance = executionService.startProcessInstanceByKey("TaskAssignee", variables);?
???
2.根據流程定義,查看流程實例?
?? 根據類ProcessDefinition的屬性ID,查看該流程的所有實例?
?? String pdId = request.getParameter("id");?
?? return executionService.createProcessInstanceQuery()?
????????? .processDefinitionId(pdId).list();?
3.執行實例?
?? 根據類ProcessInstance的屬性ID,執行流程實例?
?? String pid = request.getParameter("pid");?
?? executionService.signalExecutionById(pid);?
四.任務?
假設流程定義4-1如下:?
<process name="TaskAssignee">??
?? <start>?
????? <transition to="review" />?
?? </start>??
?? <task name="review" assignee="#{order.owner}">?
????? <transition to="work" />??
?? </task>??
?? <task name="review" assignee="johndoe">?
????? <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.4的Assignment
- 下一篇: jbpm 4.4 表结构