首先,我们来思考一个这样的逻辑,如下图,
[img]
http://dl.iteye.com/upload/picture/pic/79595/dd99a470-0acd-3bd4-b51c-ba9458c97792.png
[/img]
用文字描述是这样的:公司员工在申请借款时,首先填写借款申请,然后部门经理审批,不通过,则取消,若通过,并且金额《5000时,由财务拨款,完成申请,假如金额》=5000,则由总经理审批,通过,则由财务拨款,完成申请,不通过,取消。
通过这个流程图,我们设计jbpm流程定义文件(jbdl),实际上 上面的图就是GPD工具(图形化流程设计器)生成的,源码如下:
Loan.jpdl.xml:
[color=red](注:最开始我的name全部写的中文,发觉在运行的时候会报一个错,改成字母就好了)
有的人比较模糊task和state的区别:task有分配,state没有。[/color]
在编码过程中,我们经常会用到jbpm API服务帮我们“走”流程,上一篇中说过,jbpm中JbpmTestCase是作为jbpm4框架的单元测试超类出现的,而且帮我们初始化了如下6个流程引擎服务:
这些比较常用
再次说明,此测试类继承JbpmTestCase,很多service服务都已经初始化好了,直接run junit就ok了,它会把所有test开头的类当做测试用例执行下去,假如测试出有误,那么会给你报出来。这个例子主要是稍微熟悉一下service api,主要是对各种情况的判断或流转有一个清晰地认识。
[img]
http://dl.iteye.com/upload/picture/pic/79595/dd99a470-0acd-3bd4-b51c-ba9458c97792.png
[/img]
用文字描述是这样的:公司员工在申请借款时,首先填写借款申请,然后部门经理审批,不通过,则取消,若通过,并且金额《5000时,由财务拨款,完成申请,假如金额》=5000,则由总经理审批,通过,则由财务拨款,完成申请,不通过,取消。
通过这个流程图,我们设计jbpm流程定义文件(jbdl),实际上 上面的图就是GPD工具(图形化流程设计器)生成的,源码如下:
Loan.jpdl.xml:
<?xml version="1.0" encoding="UTF-8"?>
<process name="loan" xmlns="http://jbpm.org/4.4/jpdl">
<start name="start">
<transition name="startLoan" to="inputLoan"/>
</start>
<task assignee="#{proposer}" name="inputLoan">
<transition name="submitApplication" to="managerCheck" />
</task>
<task assignee="manager" name="managerCheck">
<transition name="managerNotPass" to="cancel" />
<transition name="managerPass" to="moneyCheck" />
</task>
<decision name="moneyCheck" expr="#{money>=5000?'x1':'x2'}">
<transition name="x1" to="ceoCheck"/>
<transition name="x2" to="financeGet"/>
</decision>
<end name="end" />
<end-cancel name="cancel" />
<task assignee="ceo" name="ceoCheck">
<transition name="ceoPass" to="financeGet" />
<transition name="ceoNotPass" to="cancel" />
</task>
<task assignee="finance" name="financeGet">
<transition name="finishFinance" to="end"/>
</task>
</process>
[color=red](注:最开始我的name全部写的中文,发觉在运行的时候会报一个错,改成字母就好了)
有的人比较模糊task和state的区别:task有分配,state没有。[/color]
在编码过程中,我们经常会用到jbpm API服务帮我们“走”流程,上一篇中说过,jbpm中JbpmTestCase是作为jbpm4框架的单元测试超类出现的,而且帮我们初始化了如下6个流程引擎服务:
//资源库服务
Protected static RepositoryService repositoryService;
//执行服务
Protected static ExecutionService executionService;
//管理服务
Protected static ManagementService managementService;
//任务服务
Protected static TaskService taskService;
//历史服务
Protected static HistoryService historyService;
//身份认证服务
Protected static IdentiryService identiryService;
这些比较常用
package org.test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.history.HistoryProcessInstance;
import org.jbpm.api.task.Task;
import org.jbpm.test.JbpmTestCase;
/**
* 模拟借款
*
* @author 阿飞哥
*
*/
public class LoanTest extends JbpmTestCase {
String deploymentId;
@Override
protected void setUp() throws Exception {
super.setUp();
deploymentId = repositoryService.createDeployment()
.addResourceFromClasspath("org/test/loan.jpdl.xml").deploy();
}
@Override
protected void tearDown() throws Exception {
repositoryService.deleteDeploymentCascade(deploymentId);
super.tearDown();
}
/************ 测试例子 ***********/
/**
* 张山 申请4000元,部门经理驳回
*/
/*public void test1(){
String curUser = "张山";
//创建流程实例
ProcessInstance pi = startLoanProcess(curUser);
String piId = pi.getId();
fillOutApplication(piId,curUser,4000);
curUser = "manager";
//部门经理不同意
managerCheck(piId,curUser,false,"最近资金紧张);
pi = executionService.findProcessInstanceById(piId);
assertNull(pi);// 结束
HistoryProcessInstance hpi = getHistoryProcessInstanceById(piId);
// 流程结束状态是cancel , 取消
assertEquals(hpi.getState(), "cancel");
}*/
/**
* 李四 申请4000元,部门经理同意
*/
public void test2(){
String curUser="李四";
//创建流程实例
ProcessInstance pi= startLoanProcess(curUser);
String piId=pi.getId();
fillOutApplication(piId,curUser,4000);
curUser="manager";
managerCheck(piId,curUser,true,"同意");//部门经理同意
pi=executionService.findProcessInstanceById(piId);
assertNotNull(pi);//流程未结束
/**
* pi.findActiveExecutionIn("financeGet")的意思是
在给出的活动名中查询处于活动的可执行活动,假如没有则返回
null
*/
assertNotNull(pi.findActiveExecutionIn("financeGet"));//财务拨款处于活动状态
/*
* Set<String> activityNames=pi.findActiveActivityNames();
* for(Iterator it=activityNames.iterator();it.hasNext();){
System.out.println(it.next());
}
*可以看看执行活动名
*/
curUser="finance";
earmark(piId,curUser,"我拨款了 哈哈");
pi=executionService.findProcessInstanceById(piId);
assertNull(pi);//流程结束
HistoryProcessInstance
hpi=getHistoryProcessInstanceById(piId);
//流程结束状态是end,正常结束
assertEquals(hpi.getState(),"ended");
}
/**
* wang wu申请6000元,部门经理同意,总经理驳回
*/
public void test3(){
String curUser="wang wu";
//创建流程实例
ProcessInstance pi= startLoanProcess(curUser);
String piId=pi.getId();
fillOutApplication(piId,curUser,6000);
curUser="manager";
managerCheck(piId,curUser,true,"同意");//部门经理同意
pi=executionService.findProcessInstanceById(piId);
assertNotNull(pi);
//既然部门经理同意,而且money>5000,那么必须得有总经理审批
assertNotNull(pi.findActiveExecutionIn("ceoCheck"));
curUser="ceo";
ceoCheck(piId,curUser,false,"不同意");//总经理驳回
pi=executionService.findProcessInstanceById(piId);
assertNull(pi);//流程结束
HistoryProcessInstance
hpi=getHistoryProcessInstanceById(piId);
//流程结束状态是cancel,取消
assertEquals(hpi.getState(),"cancel");
}
/**
* afei 申请6000,部门经理同意,总经理同意
*/
public void test4(){
String curUser="afei";
//创建流程实例
ProcessInstance pi= startLoanProcess(curUser);
String piId=pi.getId();
fillOutApplication(piId,curUser,6000);
curUser="manager";
//部门经理同意
managerCheck(piId, curUser, true,"manager ok");
pi=executionService.findProcessInstanceById(piId);
assertNotNull(pi);
assertNotNull(pi.findActiveExecutionIn("ceoCheck"));//总经理审批处于活动状态
curUser="ceo";
ceoCheck(piId, curUser, true, "ceo ok");//总经理同意
pi=executionService.findProcessInstanceById(piId);
assertNotNull(pi);
assertNotNull(pi.findActiveExecutionIn("financeGet"));//财务拨款处于活动状态
curUser="finance";
earmark(piId, curUser, "拨款");
pi=executionService.findProcessInstanceById(piId);
assertNull(pi);//流程结束
HistoryProcessInstance hpi=getHistoryProcessInstanceById(piId);
//流程结束状态是ended,正常结束
assertEquals(hpi.getState(),"ended");
}
/*** 其他方法 ***/
/**
* 用户发起借款申请
*/
public ProcessInstance startLoanProcess(String user) {
Map<String, Object> valMap = new HashMap<String, Object>();
valMap.put("proposer", user);
//创建流程实例
return executionService.startProcessInstanceByKey("loan", valMap);
}
/**
* 填写借款说明
*
* @param piId
* @param user
* @param money
* @throws Exception
*/
public void fillOutApplication(String piId, String user, double money){
List<Task> tasks = taskService.findPersonalTasks(user);//获取任务列表
Task filloutTask = null;
for (Task task : tasks) {
if (task.getExecutionId().equals(piId)) {
filloutTask = task;//匹配任务
break;
}
}
System.out.println("piId: "+piId);
assertNotNull(filloutTask);//任务不为空
Map<String, Object> valMap = new HashMap<String, Object>();
valMap.put("money", money);//申请金额
//设置变量参数
executionService.setVariables(piId, valMap);
/*
* 删除这个任务,标记相关任务为完成,
* 假如任务在流程执行的上下文中被创建,
* 这个操作可能导致一个流程实例被触发
* (这是我自己翻译的)
* */
taskService.completeTask(filloutTask.getId());
}
/**
* 部门经理审批
*
* @param piId
* @param user
* @param isPass
* @param comment
* @throws Exception
*/
public void managerCheck(String piId, String user, boolean isPass,
String comment) {
List<Task> tasks = taskService.findPersonalTasks(user);
Task checkTask = null;
for (Task task : tasks) {
if (task.getExecutionId().equals(piId)) {
checkTask = task;
break;
}
}
assertNotNull(checkTask);
taskService.addTaskComment(checkTask.getId(), comment);
taskService.completeTask(checkTask.getId(), isPass ? "managerPass"
: "managerNotPass");
}
/**
* 总经理审批
*
* @param piId
* @param user
* @param isPass
* @param comment
* @throws Exception
*/
public void ceoCheck(String piId, String user, boolean isPass,
String comment){
List<Task> tasks = taskService.findPersonalTasks(user);
Task checkTask = null;
for (Task task : tasks) {
if (task.getExecutionId().equals(piId)) {
checkTask = task;
break;
}
}
assertNotNull(checkTask);
taskService.addTaskComment(checkTask.getId(), comment);
taskService.completeTask(checkTask.getId(), isPass ? "ceoPass"
: "ceoNotPass");
}
/**
* 财务拨款
*
* @param piId
* @param user
* @param comment
*/
public void earmark(String piId, String user, String comment) {
List<Task> tasks = taskService.findPersonalTasks(user);
Task earTask = null;
for (Task task : tasks) {
if (task.getExecutionId().equals(piId)) {
earTask = task;
break;
}
}
assertNotNull(earTask);
taskService.addTaskComment(earTask.getId(), comment);
String proposer = (String) executionService.getVariable(piId,
"proposer");
// 通知借款申请人
System.out.println("hello:" + proposer + ",财务已经给你拨款了,请查收");
taskService.completeTask(earTask.getId());
}
/**
* 得到流程实例历史
* @param piId
* @return
*/
public HistoryProcessInstance getHistoryProcessInstanceById(String piId) {
return historyService.createHistoryProcessInstanceQuery()
.processInstanceId(piId).uniqueResult();
}
}
再次说明,此测试类继承JbpmTestCase,很多service服务都已经初始化好了,直接run junit就ok了,它会把所有test开头的类当做测试用例执行下去,假如测试出有误,那么会给你报出来。这个例子主要是稍微熟悉一下service api,主要是对各种情况的判断或流转有一个清晰地认识。