最近開始接觸JBPM4,網上關于JBPM4的資料少之又少。大多是關于JBPM3的。而4跟3的API差異也較大。在學習過程中做了一點關于JBPM4的筆記。強烈期望JBPM4達人能貢獻一些JBPM4方面的學習資料或視頻教程或出版發行JBPM4的書籍之類的。
本文電子版下載
流程定義引擎:
ProcessEngine processEngine;
獲取:
processEngine=Configuration.getProcessEngine();
|
重要的幾個接口:
RepositoryService repositoryService;
ExecutionService executionService;
TaskService taskService;
HistoryService historyService;
ManagementService managementService;
|
獲取:
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
taskService=processEngine.getTaskService();
historyService=processEngine.getHistoryService();
managementService=processEngine.getManagementService();
|
說明:
RepositoryService主要用來管理和發布流程定義,發布流程定義、刪除流程定義、查看流程定義。
流程定義發布:
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xml").deploy();
|
注:此方法表示從classpath路徑加載一個流程定義文件,并發布,上例中demo.jpdl.xml文件位于src(classpath)路徑下,若流程定義文件放置與包中,則需要使用包名+jpdl文件名。如com/jbpm/demo.jpdl.xml
查看流程定義:
repositoryService.createDeployment().addResourceFromClasspath("test1.jpdl.xml").deploy();
List<ProcessDefinition> list=repositoryService.createProcessDefinitionQuery().list();
for (ProcessDefinition processDefinition : list) {
System.out.println("流程定義Id:"+processDefinition.getId());
System.out.println("流程部署Id:"+processDefinition.getDeploymentId());
}
|
刪除流程定義:
String deploymentId=repositoryService.createDeployment().addResourceFromClasspath("test1.jpdl.xml").deploy();
repositoryService.deleteDeploymentCascade(deploymentId);
|
deploymentId為流程定義部署Id
ExecutionService主要用來操作流程實例,啟動流程實例、查看流程實例、刪除流程實例、結束流程實例。
其前提條件是發布了流程定義
啟動流程實例:
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xml").deploy();
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
|
使用executionService.startProcessInstanceByKey("demo");方法來啟動一個流程實例。其中startProcessInstanceByKey就表示以key的方式來啟動流程實例,key為流程定義文件中process節點的key屬性,若未明確給出key屬性,則默認key屬性的值與name屬性的值相同。
同樣也可以使用executionService.startProcessInstanceById(processDefinitionId)的方式來啟動流程實例。此方法是用流程定義文件中process節點的id屬性來啟動流程實例。
其Id屬性由兩部分組成流程定義的key和流程定義的版本來組成。形如key-version
例如:
ProcessInstance processInstance=executionService.startProcessInstanceById("demo-1");
其中demo-1就為流程定義中的流程Id,其key為demo,版本號為1
同樣使用此方法可用來啟動指定版本號的流程實例。
查看流程實例:
List<ProcessInstance> list=executionService.createProcessInstanceQuery().list();
for (ProcessInstance processInstance : list) {
System.out.println("流程實例Id:"+processInstance.getId());
System.out.println("流程定義Id:"+processInstance.getProcessDefinitionId());
}
|
級聯刪除流程實例:
executionService.deleteProcessInstanceCascade(processInstance.getId());
|
結束流程實例:
executionService.endProcessInstance(processInstance.getId(), "結束流程實例");
|
注意:在使用executionService.endProcessInstance()對流程實例進行結束操作后,需要重新查詢processInstance才能得到更新后的流程實例,如果流程已結束,則查詢結果為null
如:
executionService.endProcessInstance(processInstance.getId(), "結束流程實例");
System.out.println(processInstance.isEnded());
此行代碼是無意義的,因為此時并未獲取到更新后的流程實例,需要重新查詢流程實例,所以此處返回為false
System.out.println("-----------查詢流程實例--------------->");
List<ProcessInstance> list=executionService.createProcessInstanceQuery().list();
for (ProcessInstance processInstance : list) {
System.out.println("流程實例Id:"+processInstance.getId());
System.out.println("流程定義Id:"+processInstance.getProcessDefinitionId());
}
|
結果:
false
-----------查詢流程實例--------------->
使流程向下執行:
在使用executionService啟動流程實例后,流程會順著向下執行(即啟動流程實例后,流程會從start節點向下移動),在state或task節點,流程會暫停下來,滿足條件后流程會向下繼續執行,直到流程end節點,結束流程。
在程序中是流程遵循某一條件,沿著某個方向流動的方法為executionService.signalExecutionById();
該方法有多個重載:
ProcessInstance signalExecutionById(String executionId);
//若在流程定義某一個節點沒有分支時(只有一個transition時),調用此方法,可將流程繼續向下執行 executionId為流程實例Id
ProcessInstance signalExecutionById(String executionId, String signalName);
//若在流程定義某一個節點有多個分支時(有多個transition時),調用此方法,可將流程沿著transition所指的方向向下執行
executionId為流程實例Id, signalName為流程定義中transition節點的name屬性的值
ProcessInstance signalExecutionById(String executionId, String signalName, Map<String, ?> parameters);
用于將流程沿著signalName方向(transition的name屬性所指的方向)向下繼續執行,在執行的過程中順便傳遞參數parameters
ProcessInstance signalExecutionById(String executionId, Map<String, ?> parameters);
用于將流程向下繼續執行,在執行的過程中順便傳遞參數parameters
|
注:當一個節點有多個分支時,若要通過signalExecutionById()方法將流程向下執行必須明確指出signalName即(transition的name屬性所指的方向),否則流程不會向下執行,仍會停留在當前節點。因為jbpm不確定流程該流向那個方向。
示例代碼:
1. 沒有分支的state流向

流程定義文件:
<?xmlversion="1.0"encoding="UTF-8"?>
<processname="demo"xmlns="http://jbpm.org/4.3/jpdl">
<startname="start"g="87,113,48,48">
<transitionname="to state"to="state"g="-53,-17"/>
</start>
<statename="state"g="238,236,92,52">
<transitionname="to end"to="end"g="-41,-17"/>
</state>
<endname="end"g="384,367,48,48"/>
</process>
|
測試代碼:
import org.jbpm.api.Configuration;
import org.jbpm.api.ExecutionService;
import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.RepositoryService;
import junit.framework.TestCase;
publicclass DemoTest extends TestCase{
ProcessEngine processEngine;
RepositoryService repositoryService;
ExecutionService executionService;
@Override
protectedvoid setUp() throws Exception {
processEngine=Configuration.getProcessEngine();
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
//部署流程定義
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xml").deploy();
}
publicvoid testProcessInstance(){
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("流程實例Id:"+processInstance.getId());
System.out.println("流程定義Id:"+processInstance.getProcessDefinitionId());
//判斷當前是否位于start節點
System.out.println("是否位于start節點:"+processInstance.isActive("start"));
//判斷當前是否位于state節點
System.out.println("是否位于state節點:"+processInstance.isActive("state"));
//判斷流程是否結束
System.out.println("判斷流程是否結束:"+processInstance.isEnded());
System.out.println("------------------------>使流程繼續向下執行");
//使流程繼續向下執行
//ProcessInstance instanceState=executionService.signalExecutionById(processInstance.getId());
//此處也可以這么寫
ProcessInstance instanceState=executionService.signalExecutionById(processInstance.getId(),"to end");
//to end為流程定義中用于連接state和end節點之間transition的name屬性的值
//判斷當前是否位于state節點
System.out.println("是否位于state節點:"+instanceState.isActive("state"));
//判斷流程是否結束
System.out.println("判斷流程是否結束:"+instanceState.isEnded());
}
}
|
執行結果:
流程實例Id:demo1.7
流程定義Id:demo1-1
是否位于start節點:false
是否位于state節點:true
判斷流程是否結束:false
------------------------>使流程繼續向下執行
是否位于state節點:false
判斷流程是否結束:true
|
2. 含有分支的state流向

流程定義文件:
<?xmlversion="1.0"encoding="UTF-8"?>
<processname="demo"xmlns="http://jbpm.org/4.3/jpdl">
<startg="347,27,48,48"name="start">
<transitiong="-53,-17"name="to state"to="state"/>
</start>
<stateg="329,132,92,52"name="state">
<transitionname="to 200"to="200"g="-41,-17"/>
<transitionname="to 400"to="400"g="-41,-17"/>
</state>
<endg="358,321,48,48"name="end"/>
<statename="200"g="420,226,92,52">
<transitionname="to end"to="end"g="-41,-17"/>
</state>
<statename="400"g="266,225,92,52">
<transitionname="to end"to="end"g="-41,-17"/>
</state>
</process>
|
測試代碼:
import junit.framework.TestCase;
public class Demo2Test extends TestCase{
ProcessEngine processEngine;
RepositoryService repositoryService;
ExecutionService executionService;
@Override
protected void setUp() throws Exception {
processEngine=Configuration.getProcessEngine();
repositoryService=processEngine.getRepositoryService();
executionService=processEngine.getExecutionService();
//部署流程定義
repositoryService.createDeployment().addResourceFromClasspath("demo.jpdl.xml").deploy();
}
public void testProcessInstance(){
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("流程實例Id:"+processInstance.getId());
System.out.println("流程定義Id:"+processInstance.getProcessDefinitionId());
//判斷當前是否位于start節點
System.out.println("是否位于start節點:"+processInstance.isActive("start"));
//判斷當前是否位于state節點
System.out.println("是否位于state節點:"+processInstance.isActive("state"));
//判斷流程是否結束
System.out.println("判斷流程是否結束:"+processInstance.isEnded());
System.out.println("------------------------>使流程繼續向下執行");
//不明確指出流動方向,看流程位于那個節點
ProcessInstance instance=executionService.signalExecutionById(processInstance.getId());
//判斷當前是否位于state節點
System.out.println("是否位于state節點:"+instance.isActive("state"));
//判斷流程是否結束
System.out.println("判斷流程是否結束:"+instance.isEnded());
}
}
|
執行結果:
流程實例Id:demo.7
流程定義Id:demo-1
是否位于start節點:false
是否位于state節點:true
判斷流程是否結束:false
------------------------>使流程繼續向下執行
是否位于state節點:true
判斷流程是否結束:false
|
指明流向節點:
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
System.out.println("------------------------>使流程繼續向下執行");
System.out.println("------------------------>使流程流向200");
ProcessInstance processInstance200=executionService.signalExecutionById(processInstance.getId(), "to 200");
System.out.println("當前流程是否位于200節點---->"+processInstance200.isActive("200"));
System.out.println("當前流程是否結束---->"+processInstance200.isEnded());
/*System.out.println("------------------------>使流程流向400");
ProcessInstance processInstance400=executionService.signalExecutionById(processInstance.getId(), "to 400");
System.out.println("當前流程是否位于400節點---->"+processInstance400.isActive("400"));
System.out.println("當前流程是否結束---->"+processInstance400.isEnded());*/
|
執行效果:
------------------------>使流程繼續向下執行
------------------------>使流程流向200
當前流程是否位于200節點---->true
當前流程是否結束---->false
|
上述代碼中使用signalExecutionById()方法時,傳入的是流程實例的Id,也可以使用以下代碼來完成同樣的工作:
ProcessInstance processInstance=executionService.startProcessInstanceByKey("demo");
//查詢該流程實例的活動節點
System.out.println(processInstance.findActiveActivityNames());
//因為流程實例啟動后,它會自動向下執行,直到遇到state或task等節點時暫停下來,在我們的流程定義文件中緊跟在start后的節點為state,所以流程實例會在state節點暫停下來
Execution execution=processInstance.findActiveExecutionIn("state");
ProcessInstance processInstance200=executionService.signalExecutionById(execution.getId(), "to 200");
System.out.println("當前流程是否位于200節點---->"+processInstance200.isActive("200"));
System.out.println("當前流程是否結束---->"+processInstance200.isEnded());
//使流程繼續向下執行(結束)
System.out.println("-------使流程繼續向下執行(結束)------->");
ProcessInstance instance=executionService.signalExecutionById(processInstance200.getId());
System.out.println("當前流程是否結束---->"+instance.isEnded());
|
執行結果:
[state]
當前流程是否位于200節點---->true
當前流程是否結束---->false
-------使流程繼續向下執行(結束)------->
當前流程是否結束---->true
|
關于流程實例幾個重要的方法:
processInstance.isEnded()判斷程實例是否結束結束返回true,否則返回false
processInstance.isActive(“A”)判斷當前流程是否處于A節點
謹記executionService.signalExecutionById(String executionId, String signalName)方法中executionId為流程實例Id,signalName為流程向下執行的transition的name屬性的值,而不是下一個節點的名稱。