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