5
安裝
jBPM
的
Eclipse
開發(fā)插件
有個輔助工具開發(fā)起來方便一點,只不過現(xiàn)在
jBPM
的開發(fā)工具插件功能還不算太強,也就一個“項目創(chuàng)建向?qū)А钡墓δ?,讓你?/span>
(1)不用再去配置
classpath
庫的引用了
(2)直接得到了一個
jBPM
的項目初始結(jié)構(gòu)
其實吧,開發(fā)
jBPM
也不需要什么插件工具,在熟練了以后,庫引用了項目初始結(jié)構(gòu)都可以手工創(chuàng)建。
?
插件不用再去下載了,
jbpm-starters-kit-3.1.1
包里就有,目錄地址如下:
D:\jbpm-starters-kit-3.1.1\jbpm-designer\jbpm-gpd-feature\eclipse
,插件的安裝方式是鏈接式還是直接復(fù)制式,任選吧。不懂的就去看看《
Eclipse
從入門精通》這本書,在前面章節(jié)都有講到。另外,注明一下
Eclipse
的版本我是用
3.2
,插件和
Eclispe
版本相關(guān)的,要注意了。
?
如果安裝成功,則
Eclipse
首選項里多了一個
JBoss jBPM
,另外我們也需要到這個
jBPM
的首選項里做一些配置工作――指定
jBPM
的安裝路徑(如下圖所示)。這個配置主要是為了找到
jbpm
下的各種
jar
包,好讓
Eclipse
設(shè)置項目的庫引用。本文指向路徑是
d:\jbpm-starters-kit-3.1.1\jbpm.3
?
?
6
jBPM
的
Hello World
6.1 新建jBPM項目
主菜單“文件->新建->項目”,在彈出的對話框里,有“
Process Project
”項,如下圖所示:
?
選上好,單擊“下一步”,起個名“
myjbpm
”,然后就可以單擊“完成”了。然后就生成了如下圖所示的一個項目結(jié)構(gòu):
?
這個項目和通常
Eclipse
的項目結(jié)構(gòu)有點不同,不過這是一個現(xiàn)在非常流行的項目結(jié)構(gòu),
src/java
存放源文件,
test/java
存放相應(yīng)的
JUnit
單元測試代碼。如果你用
Maven
來編譯構(gòu)建項目,對這種目錄結(jié)構(gòu)一定不陌生。
?
項目創(chuàng)建起了,介紹一下里面的文件吧:
l??????????
MessageActionHandler
,自動生成的一個
ActionHandler
。不想要可以刪掉。
l??????????
ehcache.xml? cache
的配置文件,里面有很詳解的英文說明。沒有必要可以不用改它。
l??????????
hibernate.cfg.xml
jBPM
是用
Hibernate
進行工作流的數(shù)據(jù)存儲的,這個就是
Hibernate
的配置文件。后面我們將講到如何配置這個文件。
l??????????
jbpm.cfg.xml
jbpm
本身的配置文件?,F(xiàn)在是空的,它用的是缺省配置,你想知道有哪些配置就去看這個文件
D:\jbpm-starters-kit-3.1.1\jbpm.3\src\java.jbpm\org\jbpm\default.jbpm.cfg.xml
l??????????
log4j.properties
這個是日志
API
包
log4j
的配置文件,用過
log4j
的都知道。
l??????????
SimpleProcessTest.java
這個是對最重要的流程配置文件的
processdefinition.xml
單元測試代碼。這里表揚一點,
jBPM
的優(yōu)良設(shè)計使得它的可測試性非常之高,喜歡寫
t
單元測試的人有福了。
l??????????
gpd.xml
用于生成流程圖的定義文件。都是一些方框的坐標(biāo)和長寬
l??????????
processdefinition.xml
這個是對最重要的流程配置文件,以后寫流程要經(jīng)常和它打交道。
l??????????
processimage.jpg
一個流程圖
從項目結(jié)構(gòu)來看,我們沒有看到
JSP
網(wǎng)頁程序,也沒有看到
GUI
客戶端程序,這些代碼都是要我們以后開發(fā)中來寫的。但本文不準(zhǔn)備用
JSP
、
GUI
(
Swing
、
SWT
)來做示例,而是用
JUnit
代碼來做使用
jBPM
客戶端來演示。因為
jBPM
實際上是一個后臺框架,至于前臺是
JSP
還是
Swing
還是無界面的
java.class
都是無關(guān)緊要的。在教程里用無界面的
java.class
來做客戶端則更方便一些,如果進一步采用
JUnit
,則這樣的
java.class
同時還具備了單元測試的功能。以后就是用
JSP
寫了
WEB
頁面,我們還是可以用這些
JUnit
程序來做單元測試,避免了頻繁的鼠標(biāo)點按
WEB
頁面這樣的力氣活。所以在
jBPM
自帶的英文教程里都是一個
JUnit
程序,不仔佃看還真摸不著頭腦。
?
6.2 修改hibernate.cfg.xml
?????? hibernate.cfg.xml
的默認(rèn)設(shè)置是用
HSQL
,這是一個內(nèi)存數(shù)據(jù)庫,這種內(nèi)存數(shù)據(jù)庫用來代替項目實際所用的數(shù)據(jù)庫來做單元測試挺不錯的。不過我們這里是要試試用
MySQL
、
Oracle
,那就改一下設(shè)置吧。
注:配置值可參考
D:\jbpm-starters-kit-3.1.1\jbpm-db
對應(yīng)子目錄下的
hibernate.properties
文件。
1
、
MySQL
的更改如下:
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jbpm</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
?
2
、
Oracle
的更改如下:
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@192.168.123.10:1521:wxxrDB</property>
<property name="hibernate.connection.username">chengang</property>
<property name="hibernate.connection.password">chengang</property>
?
如果你裝了
Oracle
的客戶端,并且
D:\oracle\ora92\network\ADMIN\tnsnames.ora
里做了如下的設(shè)置
WXXRDB_192.168.123.10 =
? (DESCRIPTION =
??? (ADDRESS_LIST =
????? (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.123.10)(PORT = 1521))
??? )
??? (CONNECT_DATA =
????? (SID = wxxrDB)
????? (SERVER = DEDICATED)
??? )
? )
則
Oracle
的
hibernate.connection.url
項也可以設(shè)為:
jdbc:oracle:oci:@WXXRDB_192.168.123.10
?
6.3 完善庫引用
??????
雖然
jBPM
在創(chuàng)建項目之初給我們設(shè)置好了庫引用,如下圖
?
但后面運行時還是報一些
NoClassDefFoundError
異常,如沒有對
hibernate3.jar
的引用導(dǎo)致下面的錯誤
java.lang.NoClassDefFoundError: org/hibernate/Session
??? at org.jbpm.persistence.db.DbPersistenceServiceFactory.openService(DbPersistenceServiceFactory.java:55)
??? at org.jbpm.svc.Services.getService(Services.java:136)
??? .......
?
所以我們要為本文的實例完善庫引用。主要是把
MySQL
和
Oracle
的
JDBC
庫、以及
Hibernate
的
hibernate3.jar
加入到項目的庫引用中。
(1)??????
找到缺少的
jar
包
l??????????
mysql
的
jdbc
包,在
D:\jbpm-starters-kit-3.1.1\jbpm-db\mysql\lib
目錄里
l??????????
oracle
的
jdbc
包,
jbmp
中沒有包含(可能是沒拿到
oracle
授權(quán)),我們可以自已去
oracle
網(wǎng)站上下載,或者去
oracle
安裝目錄
D:\oracle\ora92\jdbc\lib
找
ojdbc14.jar
(我們公司用的是
Oracle9i
)
l??????????
Hibernate3.jar
在目錄
D:\jbpm-starters-kit-3.1.1\jbpm.3\lib\hibernate
里。
(2)??????
在項目里創(chuàng)建一個
lib
目錄,將這三個
jar
復(fù)制到
lib
目錄。
(3)??????
如下圖設(shè)置三
jar
包的庫引用
?
?
6.4 開始HellorWorld
這里是一個很簡單的請假流程,請假人提交假單給經(jīng)理審批,經(jīng)理審批后結(jié)束。要說明的是,這個流程并不嚴(yán)謹(jǐn),比如經(jīng)理不通過流程應(yīng)該到哪?不過這并不防礙拿它來做示例,螃蟹還得一個一個的吃。我們先拿這一桿子捅到底的流程做一個最簡單的示例,從整體上對
jBPM
工作流開發(fā)有概念先。然后我們再慢慢豐富。
?
1
、定義流程
流程的定義文件是
processdefinition.xml
,這個是一個關(guān)鍵文件,
jBPM
的很大一部份內(nèi)容都是關(guān)于它的。在這里我們把原來自動生成的內(nèi)容,稍做改動:
<?xml version="1.0" encoding="GBK"?>
?
<process-definition xmlns="urn:jbpm.org:jpdl-3.1" name="helloworld">
???
<!--
申請
-->
???
<start-state name="request">
???????
<task>
??????????? <controller>
??????????????? <variable name="name" />
??????????????? <variable name="day" />
??????????????? <variable name="note" />
???????????
</controller>
???????
</task>
???????
<!--
流程轉(zhuǎn)向
-->
??????? <transition name="to_confirm" to="confirm">
??????????? <action name="requestAction"
???????????????
class
="cn.com.chengang.jbpm.RequestAction">
??????????????? <reason>
我要請假
</reason>
???
???????
</action>
???????
</transition>
???
</start-state>
???
<!--
審批
-->
???
<state name="confirm">
??????? <transition name="to_end" to="end">
??????????? <action name="finishAction"
???????????????
class
="cn.com.chengang.jbpm.ConfirmAction" />
???????
</transition>
???
</state>
???
<!--
結(jié)束
-->
???
<end-state name="end" />
</process-definition>
說明:
流程的名稱改成了
helloworld
。(呵呵,也就是這里和
helloworld
有關(guān)了)
<controller>
標(biāo)簽定義了三個數(shù)據(jù):姓名、請假天數(shù)、說明。
<transition>
標(biāo)簽定了
request
節(jié)點的一個流程轉(zhuǎn)向,這里是轉(zhuǎn)到
confirm
節(jié)點。
<action>
標(biāo)簽定義了流程由一個節(jié)點轉(zhuǎn)到另一個節(jié)點時,所要執(zhí)行的動作,動作封裝在一個
ActionHandler
類中。比如這里當(dāng)
request
到
confirm
結(jié)點時將執(zhí)行
RequestAction
類的
execute
方法。
FinishAction
下面還有一個
<reason>
(請假理由),它對應(yīng)于
FinshAction
的屬性
String reason
。
?
2
、 編寫
ActionHandler
??????
在上面
processdefinition.xml
里我們定義了兩個
ActionHandler
:
RequestAction
、
ConfirmAction
。其代碼如下:
package
cn.com.chengang.jbpm;
?
import
org.jbpm.graph.def.ActionHandler;
import
org.jbpm.graph.exe.ExecutionContext;
?
public
class
RequestAction implements ActionHandler {
?
???
private
static
final
long
serialVersionUID
= 1L;
?
???
private
String reason;
?
???
public
String getReason() {
???????
return
reason;
??? }
?
???
public
void
setReason(String reason) {
???????
this
.reason = reason;
??? }
?
???
public
void
execute(ExecutionContext context) throws Exception {
??????? context.getContextInstance().setVariable("note", reason);
??? }
?
}
?
說明:
ExecutionContext
是一個貫通流程的容器。它是個大寶箱,里面啥玩意都有,后面將更深入的提到。這里的
reasion
就是
processdefinition.xml
中的
”
我要請假
”
?
?
package
cn.com.chengang.jbpm;
?
import
org.jbpm.graph.def.ActionHandler;
import
org.jbpm.graph.exe.ExecutionContext;
?
public
class
ConfirmAction implements ActionHandler {
?
???
private
static
final
long
serialVersionUID
= 1L;
?
???
public
void
execute(ExecutionContext context) throws Exception {
??????? context.getContextInstance().setVariable("note", "
準(zhǔn)假
"
);
??? }
?
}
?
OK
,后臺的程序就算寫完了(前臺客戶端的程序還沒寫),下面開始部署。
?
6.5 部署processdefinition.xml
??????
我們要把
processdefinition.xml
的流程定義的數(shù)據(jù)部署到數(shù)據(jù)庫中,因為
jBPM
在正式運行的時候不是去讀
processdefinition.xml
文件,而是去讀數(shù)據(jù)庫中的流程定義。
這里寫了一個個
JUnit
程序來部署
processdefinition.xml
,當(dāng)然你用普通的
Java Main
也可以。
package
com.sample;
?
import
java.io.FileInputStream;
import
java.io.FileNotFoundException;
import
java.io.InputStream;
?
import
junit.framework.TestCase;
?
import
org.jbpm.JbpmConfiguration;
import
org.jbpm.JbpmContext;
import
org.jbpm.graph.def.ProcessDefinition;
?
/**
?*
部署
processdefinition.xml
?
*
?* @author chengang
?
*
?
*/
public
class
DeployProcessTest extends TestCase {
??? /**
???
?*
在本方法執(zhí)行完畢后,檢查
jbpm_processdefinition
表會多了一條記錄
???
?
*
???
?* @throws FileNotFoundException
???
?
*/
???
public
void
testDeployProcessDefinition() throws FileNotFoundException {
??????? //
從
jbpm.cfg.xml
取得
jbpm
的配置
??????? JbpmConfiguration config = JbpmConfiguration.getInstance();
??????? //
創(chuàng)建一個
jbpm
容器
??????? JbpmContext jbpmContext = config.createJbpmContext();
??????? //
由
processdefinition.xml
生成相對應(yīng)的流程定義類
ProcessDefinition
??????? InputStream is = new FileInputStream("processes/simple/processdefinition.xml");
??????? ProcessDefinition processDefinition = ProcessDefinition.parseXmlInputStream(is);
??????? //
利用容器的方法將流程定義數(shù)據(jù)部署到數(shù)據(jù)庫上
???????
jbpmContext.deployProcessDefinition(processDefinition);
??????? //
關(guān)閉
jbpmContext
???????
jbpmContext.close();
??? }
?
}
?
運行此程序,在控制臺打印了一些日志,通過。如果出錯,仔佃閱讀出錯信息以判斷錯誤原因,并確定你按照前面兩節(jié):“修改
hibernate.cfg.xml
”和“完善庫引用”的內(nèi)容做好了設(shè)置。
?
6.6 從數(shù)據(jù)庫中的查看部署效果
無論是
MySQL
還是
Oracle
,查詢
jbpm_processdefinition
表,你會發(fā)現(xiàn)多了一條記錄,如下圖
(
以
PLSQL Developer
的顯示為例
)
?
依次檢查各表我們可以發(fā)現(xiàn)有如下變化:
?
并由此簡單判斷出各表的作用,表中各字段的作用由字段名也能知曉一二。
jbpm_processdefinition
|
一個流程定義文件對應(yīng)一條記錄,可記錄多個流程定義文件,可記錄一個流程定義文件的對個版本。
|
jbpm_action
|
記錄
ActionHandler
的對象實例(以名稱為標(biāo)識)
|
jbpm_delegation
|
記錄了
ActionHandler
全類名,以便于用反射方式來加載
|
jbpm_envent
|
它的
transition
引用了
Jbpm_transition
表的
id
,再看其它字段,估計此表是表示流程轉(zhuǎn)向事件的一個實例,或者是一個各表之間的聯(lián)接表。
|
jbpm_node
|
流程結(jié)點
|
jbpm_transition
|
流程的轉(zhuǎn)向定義
|
jbpm_variableaccess
|
流程中攜帶的變量。
ACCESS
字段是這些變量的讀寫權(quán)限
|
?
?
?作者簡介
陳剛,廣西桂林人,著作有《Eclipse從入門到精通》
您可以通過其博客了解更多信息和文章:http://www.ChenGang.com.cn?
?
??
?