jbpm5.1介紹(8)
Junit測試或流程
下面的示例中使用的是或流程,看如下流程圖
判斷節點的值是大於0,大於10還是大於20
看測試程式
public void testInclusiveSplit() throws Exception { KnowledgeBase kbase = createKnowledgeBase("BPMN2-InclusiveSplit.bpmn2"); StatefulKnowledgeSession ksession = createKnowledgeSession(kbase); Map<String, Object> params = new HashMap<String, Object>(); params.put("x", 15); ProcessInstance processInstance = ksession.startProcess( "com.sample.test", params); assertTrue(processInstance.getState() == ProcessInstance.STATE_COMPLETED); }
傳入的值是15,那麼執行結果應該是path1和path2,因為兩個節點都滿足條件
看輸出結果
Loading process BPMN2-InclusiveSplit.bpmn2 path1 path2
可以再使用其它值進行測試
Junit測試或流程2
這個示例同上,但是不同的是當執行流程結點如果沒有發現符合條件的節點那麼自動執行預設的流程
測試程式
public void testInclusiveSplitDefault() throws Exception { KnowledgeBase kbase = createKnowledgeBase("BPMN2-InclusiveSplitDefault.bpmn2"); StatefulKnowledgeSession ksession = createKnowledgeSession(kbase); Map<String, Object> params = new HashMap<String, Object>(); params.put("x", -5); ProcessInstance processInstance = ksession.startProcess( "com.sample.test", params); assertTrue(processInstance.getState() == ProcessInstance.STATE_COMPLETED); }
執行結果如下
Loading process BPMN2-InclusiveSplitDefault.bpmn2 path3
Junit測試觸發事件
這個示例是演示在執行流程的過程中觸發事件的示例,當執行到什麼的時候觸發什麼樣的流程
其中加入了兩個事件,觸發條件是YES或者No,然後在下面的程式中分別觸發
public void testEventBasedSplit() throws Exception { KnowledgeBase kbase = createKnowledgeBase("BPMN2-EventBasedSplit.bpmn2"); StatefulKnowledgeSession ksession = createKnowledgeSession(kbase); ksession.getWorkItemManager().registerWorkItemHandler("Email1", new SystemOutWorkItemHandler()); ksession.getWorkItemManager().registerWorkItemHandler("Email2", new SystemOutWorkItemHandler()); // Yes ProcessInstance processInstance = ksession .startProcess("com.sample.test"); assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE); ksession = restoreSession(ksession, true); ksession.getWorkItemManager().registerWorkItemHandler("Email1", new SystemOutWorkItemHandler()); ksession.getWorkItemManager().registerWorkItemHandler("Email2", new SystemOutWorkItemHandler()); ksession.signalEvent("Yes", "YesValue", processInstance.getId()); assertProcessInstanceCompleted(processInstance.getId(), ksession); // No processInstance = ksession.startProcess("com.sample.test"); assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE); ksession = restoreSession(ksession, true); ksession.getWorkItemManager().registerWorkItemHandler("Email1", new SystemOutWorkItemHandler()); ksession.getWorkItemManager().registerWorkItemHandler("Email2", new SystemOutWorkItemHandler()); ksession.signalEvent("No", "NoValue", processInstance.getId()); assertProcessInstanceCompleted(processInstance.getId(), ksession); }
分別觸發,得到的執行結果是
Loading process BPMN2-EventBasedSplit.bpmn2 Executing work item WorkItem 1 [name=Email1, state=0, processInstanceId=1, parameters{}] Executing Yes x=YesValue Executing work item WorkItem 2 [name=Email2, state=0, processInstanceId=1, parameters{}] Executing work item WorkItem 3 [name=Email1, state=0, processInstanceId=2, parameters{}] Executing No x=NoValue Executing work item WorkItem 4 [name=Email2, state=0, processInstanceId=2, parameters{}]
Junit測試觸發時間事件
這個示例是演示執行的過程中如果觸發時間事件將執行什麼樣的結果
流程圖如下所示
在執行的過程中在執行到時間節點後會看到有一個延時
我們這裡設定的是500ms
測試程式如下:
public void testEventBasedSplit2() throws Exception {
KnowledgeBase kbase = createKnowledgeBase("BPMN2-EventBasedSplit2.bpmn2");
StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
// Yes
ProcessInstance processInstance = ksession
.startProcess("com.sample.test");
assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ksession.signalEvent("Yes", "YesValue", processInstance.getId());
assertProcessInstanceCompleted(processInstance.getId(), ksession);
Thread.sleep(800);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ksession.fireAllRules();
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
// Timer
processInstance = ksession.startProcess("com.sample.test");
assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE);
Thread.sleep(800);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ksession.fireAllRules();
assertProcessInstanceCompleted(processInstance.getId(), ksession);
}
測試結果
Loading process BPMN2-EventBasedSplit2.bpmn2 Executing work item WorkItem 1 [name=Email1, state=0, processInstanceId=1, parameters{}] Executing Yes x=YesValue Executing work item WorkItem 2 [name=Email2, state=0, processInstanceId=1, parameters{}] Executing work item WorkItem 3 [name=Email1, state=0, processInstanceId=2, parameters{}] Executing Timer x=null Executing work item WorkItem 4 [name=Email2, state=0, processInstanceId=2, parameters{}] 會明顯看到有一個延遲執行的效果
Junit測試條件判斷
這個示例是判斷條件判斷是否可以執行,如下流程
預設情況下只觸發上邊的流程,下邊的流程只有條件滿足的情況下才能夠觸發
看一下執行的流程
public void testEventBasedSplit3() throws Exception {
KnowledgeBase kbase = createKnowledgeBase("BPMN2-EventBasedSplit3.bpmn2");
StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
Person jack = new Person();
jack.setName("Jack");
// Yes
ProcessInstance processInstance = ksession
.startProcess("com.sample.test");
assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ksession.signalEvent("Yes", "YesValue", processInstance.getId());
assertProcessInstanceCompleted(processInstance.getId(), ksession);
// Condition
processInstance = ksession.startProcess("com.sample.test");
assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ksession.insert(jack);
assertProcessInstanceCompleted(processInstance.getId(), ksession);
}
看執行結果
Loading process BPMN2-EventBasedSplit3.bpmn2 Executing work item WorkItem 1 [name=Email1, state=0, processInstanceId=1, parameters{}] Executing Yes x=YesValue Executing work item WorkItem 2 [name=Email2, state=0, processInstanceId=1, parameters{}] Executing work item WorkItem 3 [name=Email1, state=0, processInstanceId=2, parameters{}] Executing Condition x=null Executing work item WorkItem 4 [name=Email2, state=0, processInstanceId=2, parameters{}]
可以看到當流程執行到inset(jack)時觸發下面的流程
其中用到了介面
public interface WorkingMemoryEntryPoint
程式可以指定在什麼時候切入,進入切入點後就會進行流程判斷,如果滿足條件,就會如上示例,執行Condition節點並向下執行
Junit測試傳入條件事件
這個示例是判斷傳入條件的事件,根據傳入的條件觸發不同的事件執行,看一下流程
根據傳入的條件判斷
下面是測試程式碼,先傳入執行上面的流程,然後再執行下面的流程
public void testEventBasedSplit4() throws Exception {
KnowledgeBase kbase = createKnowledgeBase("BPMN2-EventBasedSplit4.bpmn2");
StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
// Yes
ProcessInstance processInstance = ksession
.startProcess("com.sample.test");
assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ksession.signalEvent("Message-YesMessage", "YesValue",
processInstance.getId());
assertProcessInstanceCompleted(processInstance.getId(), ksession);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
// No
processInstance = ksession.startProcess("com.sample.test");
ksession.signalEvent("Message-NoMessage", "NoValue",
processInstance.getId());
assertProcessInstanceCompleted(processInstance.getId(), ksession);
}
程式執行結果如下:
Loading process BPMN2-EventBasedSplit4.bpmn2 Executing work item WorkItem 1 [name=Email1, state=0, processInstanceId=1, parameters{}] Executing Yes x=YesValue Executing work item WorkItem 2 [name=Email2, state=0, processInstanceId=1, parameters{}] Executing work item WorkItem 3 [name=Email1, state=0, processInstanceId=2, parameters{}] Executing No x=NoValue Executing work item WorkItem 4 [name=Email2, state=0, processInstanceId=2, parameters{}]
Junit測試傳送任務
這個示例是測試傳送訊息的示例,流程如下結構
測試程式如下:
public void testEventBasedSplit5() throws Exception {
KnowledgeBase kbase = createKnowledgeBase("BPMN2-EventBasedSplit5.bpmn2");
StatefulKnowledgeSession ksession = createKnowledgeSession(kbase);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
ReceiveTaskHandler receiveTaskHandler = new ReceiveTaskHandler(ksession);
ksession.getWorkItemManager().registerWorkItemHandler("Receive Task",
receiveTaskHandler);
// Yes
ProcessInstance processInstance = ksession
.startProcess("com.sample.test");
assertTrue(processInstance.getState() == ProcessInstance.STATE_ACTIVE);
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
receiveTaskHandler.setKnowledgeRuntime(ksession);
ksession.getWorkItemManager().registerWorkItemHandler("Receive Task",
receiveTaskHandler);
receiveTaskHandler.messageReceived("YesMessage", "YesValue");
assertProcessInstanceCompleted(processInstance.getId(), ksession);
receiveTaskHandler.messageReceived("NoMessage", "NoValue");
ksession = restoreSession(ksession, true);
ksession.getWorkItemManager().registerWorkItemHandler("Email1",
new SystemOutWorkItemHandler());
ksession.getWorkItemManager().registerWorkItemHandler("Email2",
new SystemOutWorkItemHandler());
receiveTaskHandler.setKnowledgeRuntime(ksession);
ksession.getWorkItemManager().registerWorkItemHandler("Receive Task",
receiveTaskHandler);
// No
processInstance = ksession.startProcess("com.sample.test");
receiveTaskHandler.messageReceived("NoMessage", "NoValue");
assertProcessInstanceCompleted(processInstance.getId(), ksession);
receiveTaskHandler.messageReceived("YesMessage", "YesValue");
}
執行結果如下:
Loading process BPMN2-EventBasedSplit5.bpmn2 Executing work item WorkItem 1 [name=Email1, state=0, processInstanceId=1, parameters{}] Executing Yes x=YesValue Executing work item WorkItem 4 [name=Email2, state=0, processInstanceId=1, parameters{}] Executing work item WorkItem 5 [name=Email1, state=0, processInstanceId=2, parameters{}] Executing No x=NoValue Executing work item WorkItem 8 [name=Email2, state=0, processInstanceId=2, parameters{}]
對BPMN2.0的流程結點的說明
1.任務(Task)
任務(Task)是一個流程(Process)中的關鍵原子級的活動。Task,是用來指代一個由人或計算裝置來完成的活動,這些活動通過流程組合在一起而發揮效用。
2. Service Task
顧名思義, Service Task是通過服務(可以是Web服務,也可以是自動化程式)來完成的任務。Service Task有三個重要的屬性:
- InMessage - 只有一個輸入訊息,雖然可以有多個輸入的訊息流,但是對於Service Task的每一個例項,都只能有一個訊息流(Message Flow)能夠設定當前的輸入訊息,另外有一點要注意,就是一個Service Task要能夠接收訊息,必須先定義相應的InputSet【注:這裡的InputSet規則尚不詳盡,會在以後進行更正】。
- OutMessage - 只有一個輸出訊息,當有多個輸出流(Message Flow)時,在當前Task例項完成時,會向所有的輸出流傳送訊息。
- Implementation - 表示實現當前這個服務的實現技術,預設為Web Service,即通常為使用Web Service來完成輸入訊息的接收,並負責返回輸出訊息。
- 總結:輸入多選一,輸出全包攬。
3. Receive Task
Receive Task是用來等待外部Participant訊息的任務,一旦接收到外部訊息該任務就標記為完成狀態,很多時候,一個流程都會以一個Receive Task作為開始,通過接收一條外部訊息來啟動流程,它可以看做是一種特殊的Service Task,它只允許接收訊息,而不允許傳送訊息,Receive Task有兩條重要屬性:
- InMessage - 在規範中為Message,用來指代輸入訊息,當有多個輸入流時,只要有一流到達,當前例項任務即完成。
- Implementation - 同Service Task,指定接收的當前訊息的實現體,如一個Web Service。
4. Send Task
Send Task是一個用來向外部Participant傳送訊息的任務,一旦訊息傳送出去,該任務就完成了。同Receive Task類似,該任務,只能傳送訊息,並有一個實現體,如Web Service來負責傳送該訊息。
5. 其他Task
除了上面三個重要的Task型別,在BPMN中還有:
- User Task - 需要人在計算機的幫助下完成的任務,但UserTask的屬性都與Web Service相同,兩者的區別在於此處的UserTask並不意圖直接由Web Serivce等來執行,而是類似文件性地指出人是在什麼的幫助下完成任務的,如果使用引擎執行這裡,這裡還有尚待解決的新問題。
- Script Task - 通過引擎可識別的指令碼語言來進行自動化操作。
- Manual Task - 純人工任務,沒有計算機的參與。
- Reference Task - 相當於其他Task的引用。