JBPM 之介绍,使用
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由于各個版本之間差異比較大,所以在晚上找的很多資料跟自己使用的情況并不相符,很難找到一個完整的,能夠運行的例子(Web程序例子)。
本文以jbpm-starters-kit-3.1.2版本為例。下載地址:http://www.mirrorservice.org/sites/download.sourceforge.net/pub/sourceforge/j/project/jb/jbpm/jBPM%203/jbpm-3.1.2/。請下載:jbpm-starters-kit-3.1.2.zip版本,網上的參考資料比較多。
OK,我們接下來討論JBPM的流程圖
上圖是一個比較完整的JBPM流程圖(Finance中的子流程未寫)。
上圖的XML定義代碼:
為方便大家Copy,所有代碼均不顯示行號
<?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:
View Code
//在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自身以外的表):
View Code
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。
View Code
Start、End state是JBPM其實和結束狀態的兩個必不可少的Node。
task-node
一個task-node可以包含一個或多個task,這些task分配給特定的user。當流程執行到task-node時,taskinstance將會被創建,一個task對應一個taskinstance。taskinstances創建后,task-node就處于等待狀態。當所有的taskinstances被特定的user執行完畢后,將會發出一個新的signal到token,即流程繼續執行。
state
state是一個純粹的waitstate(等待狀態)。它和task-node的區別就是它不會創建taskinstances。很典型的用法是,當進入這個節點時(通過綁定一個action到node-enterevent),發送一條消息到外部的系統,然后流程就處于等待狀態。外部系統完成一些操作后返回一條消息,這個消息觸發一個signal到token,然后流程繼續執行。(不常用)
decision
當需要在流程中根據不同條件來判斷執行不同路徑時,就可以用decision節點。兩種方法:最簡單的是在transitions里增加conditionelements(條件),condition是beanshellscript寫的,它返回一個boolean。當運行的時候,decision節點將會在它的leavingtransitions里循環,同時比較leavingtransitions里的condition,最先返回'true'的condition,那個leavingtransitions將會被執行;作為選擇,你可以實現DecisionHandler接口,它有一個decide()方法,該方法返回一個String(leavingtransition的名字)。
fork
fork節點把一條執行路徑分離成多條同時進行(并發)的執行路徑,每條離開fork節點的路徑產生一個子token。
join
默認情況下,join節點會認為所有到達該節點的token都有著相同的父token。join節點會結束每一個到達該節點的token,當所有的子token都到達該節點后,父token會激活。當仍然有子token處于活動狀態時,join節點是waitstate(等待狀態)。
node
node節點就是讓你掛自己的action用的(注意:不是event觸發!!),當流程到達該節點時,action會被執行。你的action要實現ActionHandler接口。同樣,在你的action里要控制流程!
歡迎加入我的QQ群(JAVA開發):216672921,
總結
以上是生活随笔為你收集整理的JBPM 之介绍,使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux下的主要的C语言编译器
- 下一篇: Golang 推荐的命名规范