還沒進行實際實踐,只是就個人理解對此部分進行翻譯,肯定會有很多疏漏錯誤地方,希望諒解:
同時希望各位給予寶貴意見。謝謝!互相學習。接下來會進一步把實踐部分補上,同時對錯誤地方進行補充說明。
下面開始學習jbpm的tutorial部分的學習。
1、介紹部分:
JBpm是一個工作流管理系統(tǒng)。下面的use case圖顯示在jbpm和所有參與者之間調(diào)用關系。
《use case 圖》可以參看jbpm站點上的圖
《use case 圖》可以參看jbpm站點上的圖
《use case 圖》可以參看jbpm站點上的圖
工作流管理系統(tǒng)針對不同人員具有完全不同的含義,下面將具體解釋工作流管理系統(tǒng)四個層次上的核心職責。
Jbpm以process archives 作為輸入,一個process archive是一種業(yè)務流程的規(guī)則描述。在一個process archive被部署以后,jbpm就能夠管理這個流程的具體執(zhí)行。“管理執(zhí)行”的意思是指追蹤流程狀態(tài)(狀態(tài)層次);存儲流程執(zhí)行的信息;集成或者定制程序的邏輯例如發(fā)email,與ERP系統(tǒng)整合(程序邏輯層);允許用戶通過提交表單形式完成任務(用戶接口層)。
主要職責:一個工作流系統(tǒng)的主要職責就是維護過程執(zhí)行中的狀態(tài)。Jbpm的狀態(tài)模型以圖形形式表現(xiàn),它的主要成員就是節(jié)點和變遷(不知道翻譯的對不對,參考一些書中petri net的翻譯),一個狀態(tài)是一個節(jié)點的樣本。
運行時交互(runtime interaction):重要的交互包括:開始一個過程定義的實例和發(fā)出狀態(tài)結束的信號。這兩種jbpm交互的結果是計算出過程實例的下一個狀態(tài)。
Action:狀態(tài)圖,提供業(yè)務流程的結構,Action是程序邏輯的一些區(qū)塊(部分),程序邏輯被執(zhí)行在流程中的事件之上,有三種類型事件:進去一個節(jié)點,離開一個節(jié)點,進行一次變遷,當jbpm計算下一個狀態(tài)時候,一些事件被觸發(fā)。
Process archives:主要有用的文件就是processdefinition.xml。分析這個文件和存儲它在數(shù)據(jù)庫中的動作叫做部署一個流程。前面有所介紹,這里就不多介紹了。
接下來是介紹一個創(chuàng)建process archive的例子。很容易就可以看到,只要看過一些petri net知識的。
2、部署 process archive:
Jbpm把過程定義存儲在數(shù)據(jù)庫中。所以部署一個過程到jbpm中事實上也就是意味著分析過程定義文件processdefinition.xml并且把它存儲到jbpm數(shù)據(jù)庫中??梢酝ㄟ^兩種方式完成:
1、 運行ant 任務deploypar通過文件集合(如processdefinition.xml還有其他from文件)創(chuàng)建Process archive,deploypar部署一個process arhive到數(shù)據(jù)庫,deploypar從jbpm.properties中獲取相關屬性值。這個文件主要描述jbpm的配置選項,其中包括數(shù)據(jù)庫(process archive部署到的數(shù)據(jù)庫),更多關于此文件(jbpm.properties)的信息請參看配置部分。另外自己加一點小說明,可以參看build.xml文件里,targer name=“deploy.process.archives”部分。哪里有上面的script,包括引入的屬性文件以及部署所包含的文件。
2、 通過程序來進行部署
代碼如下:
// create a process archive input stream
String resource = "payraise/processdefinition.xml";
InputStream is = PayRaiseTest
.class
.getClassLoader()
.getResourceAsStream(resource);
ArchiveBuilder ab = new ArchiveBuilder(is);
JarInputStream jis = ab.getJarInputStream();
// deploy the process
DefinitionService ds = JbpmServiceFactory
.getInstance()
.openDefinitionService();
ds.deployProcessArchive(jis);
ds.close();
雖然上面代碼還沒看懂,大致先知道有這么一回事吧。
需要注意的是:這代碼也是用到jbpm.properties這個配置文件,包括數(shù)據(jù)庫部分。
重點:默認狀態(tài)下,jbpm配置到內(nèi)存數(shù)據(jù)庫中,這樣只是為了方便進行測試,但是當你用ant task部署流程時候,這似乎沒有什么太大作用,在這種情況下,你的數(shù)據(jù)庫就在你的運行時內(nèi)存中。所以只有在ant task完畢時才可以進入部署結果。
3、 開啟一個流程實例
在打包和部署之后,下面的顯示的代碼是教你如何啟動一個流程實例:
ExecutionService executionService =
JbpmServiceFactory.getInstance().openExecutionService("AlbertEinstein");
executionService.startProcessInstance( "payraise" );
executionService.close();
4、 獲取任務列表
一個token是一個狀態(tài)的指針,在jbpm中,每個token能指向一個參與者,因此也就創(chuàng)建了在參與者和狀態(tài)之間的關聯(lián)。在這個token思想(state-actor)背后:當引擎開始一個狀態(tài),那就意味著工作流引擎正在等待某些額外的觸發(fā)機制。如果流程定義已經(jīng)被弄好了,那這時就會計算決定正在等待誰來執(zhí)行操作,當token進入一個狀態(tài)時候,這個計算就會被執(zhí)行,所以任務里列表將是tokens(涉及到一個指定的參與者)的集合,在jbpm中參與者總是會以actorid(java.lang.string)來進行識別。
下面代碼顯示了獲取任務列表的coding :
// get an execution service for user Carl Gauss (cg)
ExecutionService executionService = JbpmServiceFactory.getInstance().openExecutionService("cg");
// get the task list for Carl Gauss (cg)
Collection tasks = executionService.getTaskList("cg");
executionService.close();
5、 結束狀態(tài)信號量
當流程實例被啟動后,jbpm計算下一個狀態(tài)以及負責此任務的責任人(參與者),流程中的計算token運行的結果是安排下一個參與者執(zhí)行任務,接下來jbpm就會告訴系統(tǒng)所有的token都在等待這個得到任務的參與者,在例子中我們假定第一個任務就是我上面啟動的的那個。(他們只是方面大家理解才舉的這個例子)。當這個參與者做了決定,他會通過調(diào)用一個方法名為endOfState來通知jbpm。
一個結束狀態(tài)信號量代碼:
ExecutionService executionService =
JbpmServiceFactory.getInstance().openExecutionService("CarlGauss");
Collection tasks = executionService.getTaskList("CarlGauss");
Token token = (Token) tasks.iterator().next();
executionService.endOfState( token.getId(), "approve" );
executionService.close();
6、 包含一個action
Jbpm另外一個重要的方面就是在過程定義中包含actions,一個action是一斷java 代碼。這些代碼必須在某個過程事件之上被執(zhí)行。假設當一個例子流程啟動后你想發(fā)個消息“message in a bottle”,你將寫代碼發(fā)送此消息作為一個actionhandler。
public class ExampleActionHandler implements ActionHandler {
public void execute(ExecutionContext executionContext) {
System.out.println( "message in a bottle" );
}
}
example action handler code
然后我們能創(chuàng)建在一個離開開始狀態(tài)的transtion(變遷)之上的一個action。
...
<start-state name="start">
<transition to="only state">
<action><delegation class="org.jbpm.example.ExampleActionHandler" /></action>
</transition>
</start-state>
...
作為最最基本的,有3種事件類型(action可以被放置):進行一個變遷,進入一個節(jié)點,離開一個節(jié)點。
7、 聲明一個變量
一個變量是一個在數(shù)據(jù)庫中的持久文本域,所以當想設置一個變量時候,jbpm不得不知道怎樣轉換對象成文本,對于下面的類型,jbpm知道如何自動轉換,它們是:
Java.lang.string
Java.lang.long
Java.lang.date
Java.lang.double
Java.io.serializable
這些變量類型在processdefinition.xml中不必聲明。Jbpm利用一個hashmap的東西來創(chuàng)建這些變量。
如果你想存儲其他java類型的變量,那么你就必須在processdefition.xml中定義一個serializer。如此:
...
<type java-type="org.jbpm.impl.YourCustomJavaType">
<delegation class="org.jbpm.impl.YourCustomSerializer" />
</type>
...
jpdl-fragment that declares a custom serializer
在這里org.jbpm.impl.YourCustomSerializer必須實現(xiàn)org.jbpm.delegation.serializer,然后,jbpm就知道如何識別你新定義的類型變量,并把它轉換成文本域(DB中)
為了避免jbpm只能自動識別serializer來使用,可以像下面這樣指定變量:
...
<type java-type="org.jbpm.impl.YourCustomJavaType">
<delegation class="org.jbpm.impl.YourCustomSerializer" />
<variable name="your-custom-var-name">
<variable name="your-second-custom-var-name">
</type>
...
jpdl-fragment that declares a custom serializer
最后是聲明變遷變量,變遷變量能被actionhandler訪問,但是,他們將被存儲到數(shù)據(jù)庫中,下面是個例子:
...
<type>
<transient />
<variable name="your-transient-var-name">
<variable name="your-second-transient-var-name">
</type>
...
jpdl-fragment that declares transient variables
8、 以客戶端訪問變量
9、 以一個action訪問變量
10、 安排任務