JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。jBPM是公开源代码项目,它使用要遵循 Apache License,。
jBPM在2004年10月18日,发布了2.0版本,并在同一天加入了JBoss,成为了JBoss企业中间件平台的一个组成部分,它的名称也改成JBoss jBPM。随着jBPM加入JBoss组织,jBPM也将进入一个全新的发展时代,它的前景是十分光明的。
jBPM最大的特色就是它的商务逻辑定义没有采用目前的一些规范,如WfMC, XPDL, BPML, ebXML, BPEL4WS等,而是采用了它自己定义的JBoss jBPM Process definition language (jPdl)。jPdl认为一个商务流程可以被看作是一个UML状态图。jPdl就是详细定义了这个状态图的每个部分,如起始、结束状态,状态之间的转换,过图型化的流程定义,直观地描述业务流程。
jBPM的另一个特色是它使用Hibernate来管理它的数据库。Hibernate是目前Java领域最好的一种数据存储层解决方案,只要是 Hibernate 支持的数据库, jBPM 也就支持.过Hibernate,jBPM将数据的管理职能分离出去,自己专注于商务逻辑的处理。
上图是一个比较完整的JBPM流程图(Finance中的子流程未写)。
上图的XML定义代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="UTF-8"?>
<process-definition
name="simple">
<start-state name="start">
<description>This process's name is simple</description>
<task name="fill reimburse">
<controller>
<variable name="baoxiaoId" access="read,write,required" mapped-name="报销ID"/>
</controller>
</task>
<transition name="" to="Manager"></transition>
</start-state>
<task-node name="Manager">
<task name="department audit">
<controller>
<variable name="baoxiaoId" access="read" mapped-name="报销ID"/>
</controller>
<assignment class="com.workflow.hander.ManagerAssignment"/>
</task>
<transition name="approve" to="AutoDecide"></transition>
<transition name="requiremodify" to="Modify"></transition>
<transition name="unapprove" to="Message"></transition>
</task-node>
<decision name="AutoDecide">
<handler class="com.workflow.hander.ProcessDecision"/>
<transition name="<10000" to="Finance"></transition>
<transition name=">10000" to="Boss"></transition>
</decision>
<task-node name="Boss">
<task name="boss audit">
<controller>
<variable name="baoxiaoId" access="read" mapped-name="报销ID"/>
</controller>
<assignment class="com.workflow.hander.BossAssignment"/>
</task>
<transition name="approve" to="Finance"></transition>
<transition name="unapprove" to="Message"></transition>
</task-node>
<process-state name="Finance">
<sub-process name="finance"/>
<variable name="baoxiaoId" access="read" mapped-name="报销ID"/>
<transition name="reimburse" to="Message"></transition>
</process-state>
<task-node name="Modify">
<task name="modify reimburse">
<controller>
<variable name="baoxiaoId" access="read,write,required" mapped-name="报销ID"/>
</controller>
<assignment class="com.workflow.hander.UserAssignment"/>
</task>
<transition name="modified" to="Manager"></transition>
<transition name="cancel" to="Message"></transition>
</task-node>
<node name="Message">
<event type="node-enter">
<action class="com.workflow.hander.ProcessResultAction"/>
</event>
<transition name="" to="end1"></transition>
</node>
<end-state name="end1"></end-state>
</process-definition>
涉及到的Java Handler:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//在start完成之后触发此Handler
public class ManagerAssignment implements AssignmentHandler {
public void assign(Assignable assignable, ExecutionContext executionContext)
throws Exception {
List<TbUser> list=new TbUserDAO().findByUserType(1);
String [] manager=new String[list.size()];
int i=0;
for (Iterator<TbUser> iter = list.iterator(); iter.hasNext();) {
TbUser el = (TbUser)iter.next();
manager[i++]=el.getUserId()+"";
}
assignable.setPooledActors(manager);
}
}
//在Manager审批完成之后(approve)触发此Handler
public class ProcessDecision implements DecisionHandler {
public String decide(ExecutionContext executionContext) throws Exception {
String baixiaoId=executionContext.getContextInstance().getVariable("baoxiaoId").toString();
TbBaoxiao baoxiao=new TbBaoxiaoDAO().findById(new Integer(Integer.parseInt(baixiaoId)));
Set<TbBaoXiaoItem> bxItem=baoxiao.getTbBaoXiaoItems();
int count=0;
for (Iterator<TbBaoXiaoItem> iter = bxItem.iterator(); iter.hasNext();) {
TbBaoXiaoItem item = (TbBaoXiaoItem) iter.next();
count+=Integer.parseInt(item.getItemMoney());
}
if(count>10000)
{
return ">10000";
}
return "<10000";
}
}
//在 Decision判断之后>1000时触发此Handler
public class BossAssignment implements AssignmentHandler {
public void assign(Assignable assignable, ExecutionContext executionContext)
throws Exception {
List<TbUser> list=new TbUserDAO().findByUserType(2);
String [] boss=new String[list.size()];
int i=0;
for (Iterator<TbUser> iter = list.iterator(); iter.hasNext();) {
TbUser el = (TbUser) iter.next();
boss[i++]=el.getUserId()+"";
}
assignable.setPooledActors(boss);
}
}
//Manager审批unapprove时出发的Handler
public class UserAssignment implements AssignmentHandler {
private static final long serialVersionUID = 1L;
public void assign(Assignable assignable, ExecutionContext executionContext)
throws Exception {
String issueUser = executionContext.getContextInstance().getVariable("issueUser").toString();
assignable.setActorId(issueUser);
}
}
//所有task结束之后触发此Handler给创建者发送Message,然后end
public class ProcessResultAction implements ActionHandler {
public void execute(ExecutionContext executionContext) throws Exception {
String baoxiaoId=executionContext.getContextInstance().getVariable("baoxiaoId").toString();
TbBaoxiaoDAO baoxiaoDao=new TbBaoxiaoDAO();
TbBaoxiao baoxiao=baoxiaoDao.findById(new Integer(Integer.parseInt(baoxiaoId)));
String issueUser=baoxiao.getTbUser().getUserName();
baoxiao.setBaoxiaoDate(new Date());
List<TbApprove> list=new TbApproveDAO().findByApproveByBaoxiaoId(baoxiao.getBaoxiaoId());
String result="驳回";
if(list.iterator().hasNext())
{
TbApprove tbapp=(TbApprove) list.iterator().next();
result=tbapp.getApproveResult();
}
baoxiao.setBaoxiaoFlag((result.indexOf("不同意")!=-1?"驳回":"批准"));
baoxiaoDao.merge(baoxiao);
StringBuffer message=new StringBuffer();
message.append(issueUser+":您好! ");
message.append("您申请的"+baoxiao.getBaoxiaoTitle());
message.append("已经被"+(result.indexOf("不同意")!=-1?"驳回":"批准"));
Message msg=new TextMessage(message.toString());
msg.setDestination(issueUser);
msg.setToken(executionContext.getProcessInstance().getRootToken());
DbMessageService msgService=new DbMessageService();
msgService.send(msg);
msgService.close();
}
}
使用的数据表(除了JBPM自身以外的表):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
CREATE TABLE tb_approve (approve_id INTEGER NOT NULL AUTO_INCREMENT, user_id INTEGER, baoxiao_id INTEGER, approve_result VARCHAR(30), approve_memo VARCHAR(300), approve_date DATETIME, PRIMARY KEY (approve_id));
CREATE TABLE tb_baoxiao (baoxiao_id INTEGER NOT NULL AUTO_INCREMENT, user_id INTEGER, baoxiao_title VARCHAR(30), baoxiao_memo VARCHAR(30), baoxiao_date DATETIME, baoxiao_flag VARCHAR(30), PRIMARY KEY (baoxiao_id));
CREATE TABLE tb_baoxiao_item (item_id INTEGER NOT NULL AUTO_INCREMENT, baoxiao_id INTEGER, item_name VARCHAR(30), item_money VARCHAR(100), PRIMARY KEY (item_id));
CREATE TABLE tb_user (user_id INTEGER NOT NULL AUTO_INCREMENT, user_name VARCHAR(30), user_password VARCHAR(30), user_type INTEGER, PRIMARY KEY (user_id));
ALTER TABLE tb_approve ADD INDEX FKD0C46A7C5C89B0A (baoxiao_id), ADD CONSTRAINT FKD0C46A7C5C89B0A FOREIGN KEY (baoxiao_id) REFERENCES tb_baoxiao (baoxiao_id);
ALTER TABLE tb_approve ADD INDEX FKD0C46A7CD355B42A (user_id), ADD CONSTRAINT FKD0C46A7CD355B42A FOREIGN KEY (user_id) REFERENCES tb_user (user_id);
ALTER TABLE tb_baoxiao ADD INDEX FKEC067E1ED355B42A (user_id), ADD CONSTRAINT FKEC067E1ED355B42A FOREIGN KEY (user_id) REFERENCES tb_user (user_id);
ALTER TABLE tb_baoxiao_item ADD INDEX FKE2F5D8945C89B0A (baoxiao_id), ADD CONSTRAINT FKE2F5D8945C89B0A FOREIGN KEY (baoxiao_id) REFERENCES tb_baoxiao (baoxiao_id);
/*
-- test Data
insert into tb_user(user_name,user_password,user_type)
values('test','123',0);
insert into tb_user(user_name,user_password,user_type)
values('manager1','123',1);
insert into tb_user(user_name,user_password,user_type)
values('manager2','123',1);
insert into tb_user(user_name,user_password,user_type)
values('boss','123',2);
insert into tb_user(user_name,user_password,user_type)
values('caiwu','123',2);
*/
以上资料具体的action和dao处理我就不贴代码了,直接说怎么进入下一个task。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Start、End state是JBPM其实和结束状态的两个必不可少的Node。
task-node
一个task-node可以包含一个或多个task,这些task分配给特定的user。当流程执行到task-node时,task instance将会被创建,一个task对应一个task instance。task instances 创建后,task-node就处于等待状态。当所有的task instances被特定的user执行完毕后,将会发出一个新的signal 到token,即流程继续执行。
state
state是一个纯粹的wait state(等待状态)。它和task-node的区别就是它不会创建task instances。很典型的用法是,当进入这个节点时(通过绑定一个action到node-enter event),发送一条消息到外部的系统,然后流程就处于等待状态。外部系统完成一些操作后返回一条消息,这个消息触发一个signal 到token,然后流程继续执行。(不常用)
decision
当需要在流程中根据不同条件来判断执行不同路径时,就可以用decision节点。两种方法:最简单的是在transitions里增加 condition elements(条件),condition是beanshell script写的,它返回一个boolean。当运行的时候,decision节点将会在它的 leaving transitions里循环,同时比较 leaving transitions里的condition,最先返回'true'的condition,那个leaving transitions将会被执行;作为选择,你可以实现DecisionHandler接口,它有一个decide()方法,该方法返回一个 String(leaving transition的名字)。
fork
fork节点把一条执行路径分离成多条同时进行(并发)的执行路径,每条离开fork节点的路径产生一个子token。
join
默认情况下,join节点会认为所有到达该节点的token都有着相同的父token。join 节点会结束每一个到达该节点的token,当所有的子token都到达该节点后,父token会激活。当仍然有子token处于活动状态时,join 节点是wait state(等待状态)。
node
node节点就是让你挂自己的action用的(注意:不是event触发!!),当流程到达该节点时,action会被执行。你的action要实现ActionHandler接口。同样,在你的action里要控制流程!