5
安裝
jBPM
的
Eclipse
開發(fā)插件
有個(gè)輔助工具開發(fā)起來方便一點(diǎn),只不過現(xiàn)在
jBPM
的開發(fā)工具插件功能還不算太強(qiáng),也就一個(gè)“項(xiàng)目創(chuàng)建向?qū)А钡墓δ埽屇悖?/span>
(1)不用再去配置
classpath
庫的引用了
(2)直接得到了一個(gè)
jBPM
的項(xiàng)目初始結(jié)構(gòu)
其實(shí)吧,開發(fā)
jBPM
也不需要什么插件工具,在熟練了以后,庫引用了項(xiàng)目初始結(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
首選項(xiàng)里多了一個(gè)
JBoss jBPM
,另外我們也需要到這個(gè)
jBPM
的首選項(xiàng)里做一些配置工作――指定
jBPM
的安裝路徑(如下圖所示)。這個(gè)配置主要是為了找到
jbpm
下的各種
jar
包,好讓
Eclipse
設(shè)置項(xiàng)目的庫引用。本文指向路徑是
d:\jbpm-starters-kit-3.1.1\jbpm.3
?
?
6
jBPM
的
Hello World
6.1 新建jBPM項(xiàng)目
主菜單“文件->新建->項(xiàng)目”,在彈出的對話框里,有“
Process Project
”項(xiàng),如下圖所示:
?
選上好,單擊“下一步”,起個(gè)名“
myjbpm
”,然后就可以單擊“完成”了。然后就生成了如下圖所示的一個(gè)項(xiàng)目結(jié)構(gòu):
?
這個(gè)項(xiàng)目和通常
Eclipse
的項(xiàng)目結(jié)構(gòu)有點(diǎn)不同,不過這是一個(gè)現(xiàn)在非常流行的項(xiàng)目結(jié)構(gòu),
src/java
存放源文件,
test/java
存放相應(yīng)的
JUnit
單元測試代碼。如果你用
Maven
來編譯構(gòu)建項(xiàng)目,對這種目錄結(jié)構(gòu)一定不陌生。
?
項(xiàng)目創(chuàng)建起了,介紹一下里面的文件吧:
l??????????
MessageActionHandler
,自動(dòng)生成的一個(gè)
ActionHandler
。不想要可以刪掉。
l??????????
ehcache.xml? cache
的配置文件,里面有很詳解的英文說明。沒有必要可以不用改它。
l??????????
hibernate.cfg.xml
jBPM
是用
Hibernate
進(jìn)行工作流的數(shù)據(jù)存儲(chǔ)的,這個(gè)就是
Hibernate
的配置文件。后面我們將講到如何配置這個(gè)文件。
l??????????
jbpm.cfg.xml
jbpm
本身的配置文件。現(xiàn)在是空的,它用的是缺省配置,你想知道有哪些配置就去看這個(gè)文件
D:\jbpm-starters-kit-3.1.1\jbpm.3\src\java.jbpm\org\jbpm\default.jbpm.cfg.xml
l??????????
log4j.properties
這個(gè)是日志
API
包
log4j
的配置文件,用過
log4j
的都知道。
l??????????
SimpleProcessTest.java
這個(gè)是對最重要的流程配置文件的
processdefinition.xml
單元測試代碼。這里表揚(yáng)一點(diǎn),
jBPM
的優(yōu)良設(shè)計(jì)使得它的可測試性非常之高,喜歡寫
t
單元測試的人有福了。
l??????????
gpd.xml
用于生成流程圖的定義文件。都是一些方框的坐標(biāo)和長寬
l??????????
processdefinition.xml
這個(gè)是對最重要的流程配置文件,以后寫流程要經(jīng)常和它打交道。
l??????????
processimage.jpg
一個(gè)流程圖
從項(xiàng)目結(jié)構(gòu)來看,我們沒有看到
JSP
網(wǎng)頁程序,也沒有看到
GUI
客戶端程序,這些代碼都是要我們以后開發(fā)中來寫的。但本文不準(zhǔn)備用
JSP
、
GUI
(
Swing
、
SWT
)來做示例,而是用
JUnit
代碼來做使用
jBPM
客戶端來演示。因?yàn)?/span>
jBPM
實(shí)際上是一個(gè)后臺框架,至于前臺是
JSP
還是
Swing
還是無界面的
java.class
都是無關(guān)緊要的。在教程里用無界面的
java.class
來做客戶端則更方便一些,如果進(jìn)一步采用
JUnit
,則這樣的
java.class
同時(shí)還具備了單元測試的功能。以后就是用
JSP
寫了
WEB
頁面,我們還是可以用這些
JUnit
程序來做單元測試,避免了頻繁的鼠標(biāo)點(diǎn)按
WEB
頁面這樣的力氣活。所以在
jBPM
自帶的英文教程里都是一個(gè)
JUnit
程序,不仔佃看還真摸不著頭腦。
?
6.2 修改hibernate.cfg.xml
?????? hibernate.cfg.xml
的默認(rèn)設(shè)置是用
HSQL
,這是一個(gè)內(nèi)存數(shù)據(jù)庫,這種內(nèi)存數(shù)據(jù)庫用來代替項(xiàng)目實(shí)際所用的數(shù)據(jù)庫來做單元測試挺不錯(cuò)的。不過我們這里是要試試用
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
項(xiàng)也可以設(shè)為:
jdbc:oracle:oci:@WXXRDB_192.168.123.10
?
6.3 完善庫引用
??????
雖然
jBPM
在創(chuàng)建項(xiàng)目之初給我們設(shè)置好了庫引用,如下圖
?
但后面運(yùn)行時(shí)還是報(bào)一些
NoClassDefFoundError
異常,如沒有對
hibernate3.jar
的引用導(dǎo)致下面的錯(cuò)誤
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)
??? .......
?
所以我們要為本文的實(shí)例完善庫引用。主要是把
MySQL
和
Oracle
的
JDBC
庫、以及
Hibernate
的
hibernate3.jar
加入到項(xiàng)目的庫引用中。
(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)??????
在項(xiàng)目里創(chuàng)建一個(gè)
lib
目錄,將這三個(gè)
jar
復(fù)制到
lib
目錄。
(3)??????
如下圖設(shè)置三
jar
包的庫引用
?
?
6.4 開始HellorWorld
這里是一個(gè)很簡單的請假流程,請假人提交假單給經(jīng)理審批,經(jīng)理審批后結(jié)束。要說明的是,這個(gè)流程并不嚴(yán)謹(jǐn),比如經(jīng)理不通過流程應(yīng)該到哪?不過這并不防礙拿它來做示例,螃蟹還得一個(gè)一個(gè)的吃。我們先拿這一桿子捅到底的流程做一個(gè)最簡單的示例,從整體上對
jBPM
工作流開發(fā)有概念先。然后我們再慢慢豐富。
?
1
、定義流程
流程的定義文件是
processdefinition.xml
,這個(gè)是一個(gè)關(guān)鍵文件,
jBPM
的很大一部份內(nèi)容都是關(guān)于它的。在這里我們把原來自動(dòng)生成的內(nèi)容,稍做改動(dòng):
<?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)簽定義了三個(gè)數(shù)據(jù):姓名、請假天數(shù)、說明。
<transition>
標(biāo)簽定了
request
節(jié)點(diǎn)的一個(gè)流程轉(zhuǎn)向,這里是轉(zhuǎn)到
confirm
節(jié)點(diǎn)。
<action>
標(biāo)簽定義了流程由一個(gè)節(jié)點(diǎn)轉(zhuǎn)到另一個(gè)節(jié)點(diǎn)時(shí),所要執(zhí)行的動(dòng)作,動(dòng)作封裝在一個(gè)
ActionHandler
類中。比如這里當(dāng)
request
到
confirm
結(jié)點(diǎn)時(shí)將執(zhí)行
RequestAction
類的
execute
方法。
FinishAction
下面還有一個(gè)
<reason>
(請假理由),它對應(yīng)于
FinshAction
的屬性
String reason
。
?
2
、 編寫
ActionHandler
??????
在上面
processdefinition.xml
里我們定義了兩個(gè)
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
是一個(gè)貫通流程的容器。它是個(gè)大寶箱,里面啥玩意都有,后面將更深入的提到。這里的
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ù)庫中,因?yàn)?/span>
jBPM
在正式運(yùn)行的時(shí)候不是去讀
processdefinition.xml
文件,而是去讀數(shù)據(jù)庫中的流程定義。
這里寫了一個(gè)個(gè)
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
表會(huì)多了一條記錄
???
?
*
???
?* @throws FileNotFoundException
???
?
*/
???
public
void
testDeployProcessDefinition() throws FileNotFoundException {
??????? //
從
jbpm.cfg.xml
取得
jbpm
的配置
??????? JbpmConfiguration config = JbpmConfiguration.getInstance();
??????? //
創(chuàng)建一個(gè)
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();
??? }
?
}
?
運(yùn)行此程序,在控制臺打印了一些日志,通過。如果出錯(cuò),仔佃閱讀出錯(cuò)信息以判斷錯(cuò)誤原因,并確定你按照前面兩節(jié):“修改
hibernate.cfg.xml
”和“完善庫引用”的內(nèi)容做好了設(shè)置。
?
6.6 從數(shù)據(jù)庫中的查看部署效果
無論是
MySQL
還是
Oracle
,查詢
jbpm_processdefinition
表,你會(huì)發(fā)現(xiàn)多了一條記錄,如下圖
(
以
PLSQL Developer
的顯示為例
)
?
依次檢查各表我們可以發(fā)現(xiàn)有如下變化:
?
并由此簡單判斷出各表的作用,表中各字段的作用由字段名也能知曉一二。
jbpm_processdefinition
|
一個(gè)流程定義文件對應(yīng)一條記錄,可記錄多個(gè)流程定義文件,可記錄一個(gè)流程定義文件的對個(gè)版本。
|
jbpm_action
|
記錄
ActionHandler
的對象實(shí)例(以名稱為標(biāo)識)
|
jbpm_delegation
|
記錄了
ActionHandler
全類名,以便于用反射方式來加載
|
jbpm_envent
|
它的
transition
引用了
Jbpm_transition
表的
id
,再看其它字段,估計(jì)此表是表示流程轉(zhuǎn)向事件的一個(gè)實(shí)例,或者是一個(gè)各表之間的聯(lián)接表。
|
jbpm_node
|
流程結(jié)點(diǎn)
|
jbpm_transition
|
流程的轉(zhuǎn)向定義
|
jbpm_variableaccess
|
流程中攜帶的變量。
ACCESS
字段是這些變量的讀寫權(quán)限
|
?
?
?作者簡介
陳剛,廣西桂林人,著作有《Eclipse從入門到精通》
您可以通過其博客了解更多信息和文章:http://www.ChenGang.com.cn?
?
??
?