JBPM API
流程運(yùn)行模式:定義完流程之后,流程定義在運(yùn)行時(shí)被實(shí)例化,因此我們要?jiǎng)?chuàng)建流程定義實(shí)例;當(dāng)流程實(shí)例在執(zhí)行中時(shí),我們要控制和監(jiān)視流程,以保證業(yè)務(wù)流程執(zhí)行在監(jiān)控中;當(dāng)流程實(shí)例執(zhí)行完畢,jbpm4會(huì)將其歸檔為歷史流程中去,從而提高運(yùn)行中流程實(shí)例的執(zhí)行效率。
Service API實(shí)現(xiàn)的功能:
1.管理流程部署
2.管理流程實(shí)例
3.管理流程任務(wù)
4.管理流程歷史
5.以及管理流程的一切
?
5.1流程定義.流程實(shí)例和執(zhí)行的概念
流程定義:是對(duì)業(yè)務(wù)過程步驟的描述,在jbpm4中它表現(xiàn)為若干"活動(dòng)"節(jié)點(diǎn)通過“轉(zhuǎn)移”線條串聯(lián)。
流程實(shí)例:表示流程定義在運(yùn)行時(shí)特有的執(zhí)行例程。
可以把流程定義理解為JavaClass定義,而流程實(shí)例可以理解為Java Class定義實(shí)例化生成Java Object對(duì)象。
信貸流程定義實(shí)例
一個(gè)流程實(shí)例在其生命周期中最典型的特征就是具有指向當(dāng)前執(zhí)行活動(dòng)的指針------"執(zhí)行"
信貸流程實(shí)例執(zhí)行實(shí)例
執(zhí)行在jbpm3中被稱為token,在jbpm4中變?yōu)閑xecutions
流程實(shí)例支持并行執(zhí)行,所以在同一個(gè)流程實(shí)例中的執(zhí)行數(shù)量并非絕對(duì)為唯一,修改匯款"write money"和存檔"archive"被定義并執(zhí)行,那么主流流程實(shí)例就包含了兩個(gè)用來跟蹤狀態(tài)的子執(zhí)行。
?
信貸流程實(shí)例并行執(zhí)行實(shí)例
流程實(shí)例一般可以理解為一顆執(zhí)行樹,當(dāng)一個(gè)流程實(shí)例啟動(dòng)時(shí)最初的執(zhí)行處于這個(gè)執(zhí)行樹的根節(jié)點(diǎn)位置,之后根據(jù)定義的需要產(chǎn)生子執(zhí)行,即樹枝。
Jbpm使用樹狀執(zhí)行結(jié)構(gòu)的原因:實(shí)際上只有一條執(zhí)行路徑,所以子執(zhí)行終將歸于(join)根執(zhí)行。
5.2流程引擎API
流程引擎對(duì)象org.jbpm.api.ProcessEngine是Jbpm4所有ServiceAPI之源,所有的seviceApi都從ProcessEngine中獲得
// processEngine從Configuration獲得,是線程安全的,保存在靜態(tài)變量中
//甚至JNDI命名服務(wù)或者其他重要位置
ProcessEngine processEngine = configuration.buildProcessEngine();
?
//自定義其他位置的jbpm配置文件
ProcessEngine processEngine =new Configuration.setResource("my-jbpm-confguration-file.xml").buildProcessEngine();
?
// Obtain the services from the process engine
//jbpm4中對(duì)外統(tǒng)一服務(wù)的6個(gè)service api
RepositoryService repositoryService = processEngine.getRepositoryService();
ExecutionService executionService = processEngine.getExecutionService();
TaskService taskService = processEngine.getTaskService();
HistoryService historyService = processEngine.getHistoryService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService=processEngine.getIdentityService();
1.RepositoryService:流程資源服務(wù)接口。提供對(duì)流程定義的部署查詢和刪除操作。
2. ExecutionService:流程執(zhí)行服務(wù)接口。提供啟動(dòng)流程實(shí)例.執(zhí)行推進(jìn)和設(shè)置流程變量等操作。
3.TaskService :流程任務(wù)服務(wù)接口。提供對(duì)任務(wù)的創(chuàng)建.提交.查詢.保存和刪除操作
4.ManagementService :流程管理控制服務(wù)接口。提供對(duì)異步工作(Job)相關(guān)的執(zhí)行和查詢工作
5.HistoryService :流程歷史服務(wù)接口。提供對(duì)流程歷史庫(即已完成的流程實(shí)例歸檔)中歷史流程實(shí)例.歷史活動(dòng)實(shí)例等記錄的查詢工作。還提供諸如某個(gè)流程定義中所有活動(dòng)的平均持續(xù)時(shí)間.某個(gè)流程定義中某轉(zhuǎn)移的經(jīng)過次數(shù)等數(shù)據(jù)分析服務(wù)
6.IdentityService 身份認(rèn)證服務(wù)接口。提供對(duì)流程用戶.用戶組以及組成員關(guān)系的相關(guān)服務(wù)。
public class AbstractServiceImpl {
?
protected CommandService commandService;
?
public CommandService getCommandService() {
return commandService;
}
?
public void setCommandService(CommandService commandService) {
this.commandService = commandService;
}
}
CommandService 是Command模式的服務(wù)接口,是將客戶端的請(qǐng)求全部封裝在一個(gè)調(diào)用接口中,然后由這個(gè)接口去調(diào)用org.jbpm.api.cmd.Command接口的眾多實(shí)現(xiàn)。
*jbpm4 Sevice API的實(shí)現(xiàn)廣泛地采用了Command設(shè)計(jì)模式,何謂Command模式?Jbpm4為什么要采用Command模式?
抽象出待執(zhí)行的動(dòng)作以參數(shù)化某對(duì)象,您可用面向過程語言中的回調(diào)(callback)函數(shù)表達(dá)這種參數(shù)化機(jī)制。所謂回調(diào)函數(shù)是指函數(shù)現(xiàn)在某處注冊(cè),而它將在稍后某個(gè)需要的時(shí)候被調(diào)用??梢哉fCommand模式是回調(diào)機(jī)制的一個(gè)面向?qū)ο蟮奶娲贰?/p>
Command模式的目的即在不同的時(shí)刻指定.排列和執(zhí)行請(qǐng)求。一個(gè)Command對(duì)象可以有一個(gè)與初始化請(qǐng)求無關(guān)的生存期。如果一個(gè)請(qǐng)求的接受者可用一種與地址空間無關(guān)的方式表達(dá),那么就可將負(fù)責(zé)該請(qǐng)求的命令對(duì)象傳遞給另一個(gè)不同的進(jìn)程并在那兒實(shí)現(xiàn)該請(qǐng)求。
Command模式的優(yōu)勢在于:
支持取消操作。
支持修改日志。
用構(gòu)建在原語操作的高層操作構(gòu)建一個(gè)系統(tǒng)。
5.3利用API部署流程
//使用 repositoryService提供的API方法從classpath中部署流程定義
deploymentId = repositoryService.createDeployment()
.addResourceFromClasspath(
"org/jbpm/examples/services/Order.jpdl.xml").deploy();
//當(dāng)然在這里可以多次調(diào)用addResourceFromClasspath方法,將流程定義的其他資源都將部署到數(shù)據(jù)庫中
通過addResourceFromXXX系列方法,流程定義XML內(nèi)容可以從文件,WebURL.字符串.輸入流或Zip流中獲取。每次部署的資源的內(nèi)容都是字節(jié)數(shù)組的形式。jPDL流程定義文件以擴(kuò)展名.jpdl.xml被識(shí)別。其他資源文件包括任務(wù)表單.Java類和腳本等。如果不竟要部署.jpdl.xml流程定義文件,而且要部署一系列流程定義資源,則可以以流程定義歸檔的方式部署,流程引擎會(huì)自動(dòng)識(shí)別歸檔中擴(kuò)展名為.jpdl.xml文件為流程定義文件。
<</SPAN>process name="Order" xmlns="http://jbpm.org/4.3/jpdl">
?
</</SPAN>process>
?
屬性名稱 | 屬性值 | 來源 |
Name | Order | 流程定義語言 |
Key | Order(把不是字母或數(shù)字替換成下劃線) | 系統(tǒng)生成 |
Version | 1(版本號(hào)自動(dòng)遞增) | 系統(tǒng)生成 |
Id | Order -1 | 系統(tǒng)生成 |
?
?
5.4通過API刪除已部署的流程
repositoryService.deleteDeploymentCascade(deploymentId);
這個(gè)方法是物理上的刪除會(huì)在數(shù)據(jù)庫中徹底銷毀這條流程定義的記錄
級(jí)聯(lián)刪除使用deleteDeploymentCascade方法
5.5使用API發(fā)起新的流程實(shí)例
5.5.1發(fā)起流程的常規(guī)方法
ProcessInstance processInstance=executionService.startProcessInstanceByKey("order");
startProcessInstanceByKey方法會(huì)去查找key為order的最新版本的流程定義,然后根據(jù)最新版本的流程定義啟動(dòng)流程實(shí)例。也可以通過id來發(fā)起startProcessInstanceById
5.5.2指定業(yè)務(wù)鍵發(fā)起流程
ProcessInstance processInstance=executionService.startProcessInstanceByKey("order",“Order0098”);
業(yè)務(wù)鍵是用戶執(zhí)行流程的時(shí)候根據(jù)業(yè)務(wù)定義的。一個(gè)業(yè)務(wù)鍵必須在流程定義所有的版本的流程實(shí)例范圍內(nèi)都是唯一的。提供一個(gè)業(yè)務(wù)鍵的好處為可以根據(jù)業(yè)務(wù)來執(zhí)行流程實(shí)例搜索
5.5.3根據(jù)變量發(fā)起流程實(shí)例
//創(chuàng)建并填充流程變量
Map variables=new HashMap();
variables.put("customerName", "Alex Miller");
variables.put("type", "Accident");
variables.put("amount", new Float(763.74));
//傳入Map,帶著流程變量發(fā)起例程實(shí)例
ProcessInstance processInstance=executionService.startProcessInstanceByKey(
?
5.6喚醒一個(gè)等待的執(zhí)行
當(dāng)流程執(zhí)行進(jìn)入state活動(dòng)時(shí),執(zhí)行會(huì)在到達(dá)state活動(dòng)的時(shí)候進(jìn)入等待狀態(tài)-wait satate,這是jbpm的一個(gè)重要概念,task等活動(dòng)也會(huì)陷入等待狀態(tài),直到signal(可以理解一個(gè)“外部觸發(fā)信號(hào)”)出現(xiàn),才能進(jìn)入下一個(gè)步驟的活動(dòng)。ExecutionService的signalExecution方法可以用來發(fā)出signal這個(gè)方法傳入執(zhí)行對(duì)象。
獲取正確的執(zhí)行比較好的實(shí)踐是給state活動(dòng)分配一個(gè)事件監(jiān)聽器,定義如下:
<</SPAN>state name="receive confirmation" g="96,16,136,52">
?
....
</</SPAN>state>
在監(jiān)聽器StartExternalWork類中,,可以執(zhí)行那些需要在state活動(dòng)完成的工作。在這個(gè)事件監(jiān)聽器中通過executionId=execution.getId();獲得正確的執(zhí)行id,,在state活動(dòng)的工作完成之后,可以用它發(fā)出signal離開該活動(dòng)。
executionService.signalExecutionById(executionId);
?
//以下代碼假設(shè)我們知道當(dāng)前活動(dòng)的名稱,用它來開啟活動(dòng)
ProcessInstance processInstance=executionService.startProcessInstanceById(processDefinitionId);
//或
//ProcessInstance processInstance=executionService.signalExecutionById(executionId);
//如上述假設(shè),我們知道當(dāng)前流程實(shí)例為"external work"的活動(dòng)中等待
Execution execution=processInstance.findActiveExecutionIn("external work");
//獲取執(zhí)行ID
String executionId=execution.getId();
5.7任務(wù)服務(wù)API
TaskService的主要目的是提供對(duì)任務(wù)列表的訪問操作,這里的任務(wù)是指Jbpm task活動(dòng)產(chǎn)生的人機(jī)交互業(yè)務(wù)。
//獲得Id為alexmiller的任務(wù)列表
List<</SPAN>Task> taskList=taskService.findPersonalTasks("alexmiller");
//讀取任務(wù)變量
long taskId=task.getId();
Set variableNames=taskService.getVariableNames(taskId);
//讀取任務(wù)變量
HashMap variables=taskService.getVariableNames(taskId,variableNames);
//或自行創(chuàng)建variableNames=new HashMap();
//設(shè)置"鍵-值"形式的任務(wù)變量
variables.put("ctegory", "sma11");
variables.put("lires", 9332323);
//將變量存入任務(wù)
taskService.setVariables(taskId, variables);
?
//TaskService完成任務(wù)的四種方式:
//根據(jù)指定的任務(wù)ID完成任務(wù)
taskService.completeTask(taskId);
//根據(jù)指定的任務(wù)ID完成任務(wù),同時(shí)設(shè)入變量,完成任務(wù)
taskService.completeTask(taskId,variableNames);
//指定outcome,即系一部的轉(zhuǎn)移路徑,完成任務(wù)
taskService.completeTask(taskId,outcome);
//指定下一步的轉(zhuǎn)移路徑,同時(shí)設(shè)入變量,完成任務(wù)
taskService.completeTask(taskId,outcome,variableNames);
?
Outcome這個(gè)參數(shù)可以用來決定任務(wù)完成后流程流向那個(gè)流出“轉(zhuǎn)移”。完成任務(wù)后,流程將“何去何從”遵循如下的規(guī)則:
1>如果任務(wù)擁有一個(gè)沒有名稱的流出轉(zhuǎn)移:
A>taskService.getOutcomes(taskId)返回包含一個(gè)null值的集合
B>taskService.completeTask(taskId)會(huì)經(jīng)過這個(gè)流出轉(zhuǎn)移
C>taskService.completeTask(taskId,null)會(huì)通過這個(gè)流出轉(zhuǎn)移
D>taskService.completeTask(taskId,"anyvalue")會(huì)拋出一個(gè)異常
2>如果任務(wù)擁有一個(gè)已命名為myName的流出轉(zhuǎn)移
A>taskService.getOutcomes(taskId)返回包含這個(gè)流出轉(zhuǎn)移的名稱集合
B>taskService.completeTask(taskId)會(huì)經(jīng)過這個(gè)流出轉(zhuǎn)移
C>taskService.completeTask(taskId,null)會(huì)拋出一個(gè)異常。因?yàn)榇巳蝿?wù)沒有無名稱的流出轉(zhuǎn)移。
D>taskService.completeTask(taskId,"anyvalue")會(huì)拋出一個(gè)異常
E>taskService.completeTask(taskId,"myName")會(huì)經(jīng)過這個(gè)流出轉(zhuǎn)移
3>如果任務(wù)擁有多個(gè)流出轉(zhuǎn)移,而其中一個(gè)沒有名稱,其他都有名稱。
A>taskService.getOutcomes(taskId)返回包含一個(gè)null值和其他流出轉(zhuǎn)移的名稱集合
B>taskService.completeTask(taskId)會(huì)經(jīng)過沒有名稱的流出轉(zhuǎn)移
C>taskService.completeTask(taskId,null)會(huì)經(jīng)過沒有名稱的流出轉(zhuǎn)移
D>taskService.completeTask(taskId,"anyvalue")會(huì)拋出一個(gè)異常
E>taskService.completeTask(taskId,"myName")會(huì)經(jīng)過名稱為myName的流出轉(zhuǎn)移(我們假設(shè)myName存在有名稱的流出轉(zhuǎn)移中)
4>如果任務(wù)擁有多個(gè)流出轉(zhuǎn)移,且每個(gè)流出轉(zhuǎn)移都擁有唯一的名稱。
A>taskService.getOutcomes(taskId)包含所有流出轉(zhuǎn)移名稱的集合 B>taskService.completeTask(taskId)會(huì)拋出一個(gè)異常。因?yàn)闆]有無名稱的流出轉(zhuǎn)移
C>taskService.completeTask(taskId,null)會(huì)拋出一個(gè)異常。因?yàn)闆]有無名稱的流出轉(zhuǎn)移
D>taskService.completeTask(taskId,"anyvalue")會(huì)拋出一個(gè)異常
E>taskService.completeTask(taskId,"myName")會(huì)經(jīng)過名稱為myName的流出轉(zhuǎn)移(我們假設(shè)myName存在有名稱的流出轉(zhuǎn)移中)
任務(wù)可以擁有多個(gè)候選人,候選人可以是單個(gè)用戶也可以是用戶組。用戶可以接收候選人是自己的任務(wù),接受任務(wù)的意思是用戶被流程引擎設(shè)置為任務(wù)的分配者。接收任務(wù)是個(gè)”排他“操作,因此在任務(wù)被”接收-分配“之后,其他的用戶就不能接收并辦理此任務(wù)。用戶接收任務(wù)后,一般需要客戶端應(yīng)用程序界面顯示任務(wù)表單,并引導(dǎo)用戶完成任務(wù)。對(duì)于有候選人,但是還沒有被分配的任務(wù),唯一應(yīng)該暴露給用戶的操作是”接受任務(wù)“
5.8歷史服務(wù)API
在流程實(shí)例執(zhí)行的流程中,會(huì)不斷觸發(fā)事件,通過這些事件,已完成流程實(shí)例的歷史信息會(huì)被征集到流程歷史數(shù)據(jù)庫中。而HistoryServcieAPI提供了對(duì)這些歷史信息的訪問服務(wù)。
//查找特定流程定義的所有歷史流程實(shí)例
List<</SPAN>HistoryProcessInstance> historyProcessInstances=historyService.createHistoryDetailQuery()
//查詢Id為“ICL-1”
.processDefinitionId("ICL-1")
//返回的結(jié)果集按開始時(shí)間正序排列
.oderAsc(HistoryProcessInstanceQuery.PROPERTY_STARTTIME)
.list();
//歷史的活動(dòng)實(shí)例被HistoryActivtyInstance查詢歷史列表
List<</SPAN>HistoryActivityInstance> historyActInsts=historyService
.createHistoryActivityInstanceQuery()
//查詢ID為“ICL-1”的流程定義
.processDefinitionId("ICL-1")
.activityName("a")
.list();
avgDurtionPerActivity--獲取指定流程定義中每個(gè)活動(dòng)的平均執(zhí)行時(shí)間
choiceDistribution---獲取指定活動(dòng)定義每個(gè)轉(zhuǎn)移的經(jīng)過次數(shù)
5.9管理服務(wù)API
ManagementService即管理服務(wù),通常用來管理Job,在jbpm4 web控制臺(tái)等客戶端應(yīng)用上被調(diào)用
//提供以下兩個(gè)方法
//執(zhí)行指定ID的Job
Void execteJob(String jobId);
//獲取Job查詢接口
JobQuery createJobQurey();
?
?
public interface JobQuery {
?
?
public static final String PROPERTY_DUEDATE = "duedate";
?
public static final String PROPERTY_STATE = "state";
?
?
JobQuery messages();
?
?
JobQuery timers();
?
JobQuery processInstanceId(String processInstanceId);
?
JobQuery exception(boolean hasException);
?
?
JobQuery orderAsc(String property);
?
?
JobQuery orderDesc(String property);
?
JobQuery page(int firstResult, int maxResults);
?
List list();
?
Job uniqueResult();
?
long count();
}
5.10查詢服務(wù)API
查詢服務(wù)API是基于主要的jBPM概念實(shí)體上創(chuàng)建查詢對(duì)象來實(shí)現(xiàn)的,這個(gè)概念的實(shí)體包括流程實(shí)例.任務(wù).流程歷史
//對(duì)流程實(shí)例的查詢
//對(duì)流程實(shí)例的查詢
List results=executionService
//獲取流程實(shí)例查詢對(duì)象
.createProcessInstanceQuery()
//指定流程定義Id
.processDefinitionId("my_process_defintion")
//設(shè)定“為掛起”為過渡條件
.notSuspended()
//分頁
.page(0, 50)
//查詢執(zhí)行,獲得結(jié)果列表
.list();
//上面代碼放回指定流程定義的所有未掛起的流程,結(jié)果集支持分頁,獲取前50條記錄
?
?
//對(duì)于任務(wù)的查詢也可以使用類似的查詢對(duì)象
List myTasks=taskService
//獲取任務(wù)查詢對(duì)象
.createTaskQuery()
//指定流程定義Id
.processInstanceId(piId)
//分配給Alex任務(wù)
.assignee("Alex")
//分頁
.page(100, 120)
//根據(jù)日期逆向排序
.orderDesc(TaskQuery.PROPERTY_DUEDATE)
//查詢執(zhí)行,獲得結(jié)果列表
.list();
5.11例程:利用jbpm service api完成流程實(shí)例
本例程演示如何利用jbpm service api基于一個(gè)簡單的流程定義,發(fā)起,執(zhí)行.完成整個(gè)流程實(shí)例并查詢?cè)摿鞒虒?shí)例的歷史記錄。
首先,流程定義如下
對(duì)應(yīng)的jpdl
總結(jié)
- 上一篇: 微信、企业微信和支付窗 SDK 三合一,
- 下一篇: java StringBuffer常用方