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