jbpm5.1介绍(8)

时间:2022-05-05
本文章向大家介绍jbpm5.1介绍(8),主要内容包括1.任务(Task)、2. Service Task、3. Receive Task、4. Send Task、5. 其他Task、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

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有三个重要的属性:

  1. InMessage - 只有一个输入消息,虽然可以有多个输入的消息流,但是对于Service Task的每一个实例,都只能有一个消息流(Message Flow)能够设置当前的输入消息,另外有一点要注意,就是一个Service Task要能够接收消息,必须先定义相应的InputSet【注:这里的InputSet规则尚不详尽,会在以后进行更正】。
  2. OutMessage  - 只有一个输出消息,当有多个输出流(Message Flow)时,在当前Task实例完成时,会向所有的输出流发送消息。
  3. Implementation - 表示实现当前这个服务的实现技术,默认为Web Service,即通常为使用Web Service来完成输入消息的接收,并负责返回输出消息。
  4. 总结:输入多选一,输出全包揽。

3. Receive Task

Receive Task是用来等待外部Participant消息的任务,一旦接收到外部消息该任务就标记为完成状态,很多时候,一个流程都会以一个Receive Task作为开始,通过接收一条外部消息来启动流程,它可以看做是一种特殊的Service Task,它只允许接收消息,而不允许发送消息,Receive Task有两条重要属性:

  1. InMessage - 在规范中为Message,用来指代输入消息,当有多个输入流时,只要有一流到达,当前实例任务即完成。
  2. Implementation - 同Service Task,指定接收的当前消息的实现体,如一个Web Service。

4. Send Task

Send Task是一个用来向外部Participant发送消息的任务,一旦消息发送出去,该任务就完成了。同Receive Task类似,该任务,只能发送消息,并有一个实现体,如Web Service来负责发送该消息。

5. 其他Task

除了上面三个重要的Task类型,在BPMN中还有:

  1. User Task - 需要人在计算机的帮助下完成的任务,但UserTask的属性都与Web Service相同,两者的区别在于此处的UserTask并不意图直接由Web Serivce等来执行,而是类似文档性地指出人是在什么的帮助下完成任务的,如果使用引擎执行这里,这里还有尚待解决的新问题。
  2. Script Task - 通过引擎可识别的脚本语言来进行自动化操作。
  3. Manual Task - 纯人工任务,没有计算机的参与。
  4. Reference Task - 相当于其他Task的引用。