jbpm学习笔记(七) fork-join活动详解以及示例,对处理流程的一点想法

今天继续学习jbpm活动元素之 fork-join(分支/聚合活动)

当我们需要流程并发(concurrency)执行的时候,就需要使用到fork-join活动组合,fork活动可以使流程在一条主干上出现并行的分支,join活动则可以使流程的并行分支聚合成一条主干。
Fork活动仅具有jbpm活动的最基本特征,即具有1个name属性和n个流出转移元素。
相关jpdl如下:
<?xml version="1.0" encoding="UTF-8"?>

<process name="forkAndJoin" xmlns="http://jbpm.org/4.4/jpdl">
<start>
<transition to="fork" />
</start>

<!-- 流程在此产生 3个并行的分支 -->
<fork name="fork">
<transition to="pingpang" />
<transition to="football" />
<transition to="basketball" />
</fork>


<state name="pingpang">
<transition to="to playball" /><!-- 就是打一般的球 -->
</state>

<!-- 足球和篮球属于大球 会join到to play bigball活动上去-->
<state name="football">
<transition to="to play bigball" />
</state>

<state name="basketball">
<transition to="to play bigball" />
</state>


<!-- 在此定义to play bigball的join活动 -->
<join name="to play bigball">
<transition to="play bigball" /> <!-- 开始打大球 -->
</join>

<state name="play bigball">
<transition to="to playball" /><!-- 其实是一起去打普通的球 -->
</state>


<join name="to playball">
<transition to="play over" /><!-- 打球马上结束了 -->
</join>

<end name="play over"/>


</process>


编写单元测试代码执行上面的流程定义

package org.test;

import java.util.HashSet;
import java.util.Set;

import org.jbpm.api.ProcessInstance;
import org.jbpm.test.JbpmTestCase;

public class ForkAndJoinTest extends JbpmTestCase {

String deploymentId;

@Override
public void setUp() throws Exception {
super.setUp();
deploymentId = repositoryService.createDeployment()
.addResourceFromClasspath("org/test/forkAndJoin.jpdl.xml")
.deploy();
}

@Override
public void tearDown() throws Exception {
repositoryService.deleteDeploymentCascade(deploymentId);
super.tearDown();
}

public void testForkAndJoin() {
// 发起forkAndJoin流程实例
ProcessInstance pi = executionService
.startProcessInstanceByKey("forkAndJoin");
String pid = pi.getId();

// 构造一个活动名称集合以验证分支。设置3个分支活动的名称
Set<String> ballsName = new HashSet<String>();
ballsName.add("pingpang");
ballsName.add("football");
ballsName.add("basketball");

// 断言当前活动即为产生的3个分支
assertEquals(ballsName, pi.findActiveActivityNames());

// 发出执行信号通过 "pingpang" 活动,这时候,流程会在最后的聚合活动"play"上等待其他分支的到来
String pingpangExecuId = pi.findActiveExecutionIn("pingpang").getId();
pi = executionService.signalExecutionById(pingpangExecuId);
// 在活动名称集合中排除 "pingpang"活动
ballsName.remove("pingpang");

// 此时,仍然可以断言另外2个分支还在等待
assertNotNull(pi.findActiveExecutionIn("football"));
assertNotNull(pi.findActiveExecutionIn("basketball"));

// 发出执行信号通过剩下的其中一个分支--football活动
String footballExecuId = pi.findActiveExecutionIn("football").getId();
pi = executionService.signalExecutionById(footballExecuId);
// 在活动名称集合中排除 "football"活动
ballsName.remove("football");

// 发出执行信号通过剩下的第二个分支--basketball活动
String basketballExecuId = pi.findActiveExecutionIn("basketball")
.getId();
pi = executionService.signalExecutionById(basketballExecuId);
// 在活动名称集合中排除"basketball"活动
ballsName.remove("basketball");

// size应该是0
System.out.println("ballsName.size(): " + ballsName.size());

// 断言通过了第一个聚合活动 "to play bigball",到达了"play bigball"活动
assertNotNull(pi.findActiveExecutionIn("play bigball"));

//发出执行信号通过"play bigball"活动
String playBigBallExecuId=pi.findActiveExecutionIn("play bigball").getId();
pi=executionService.signalExecutionById(playBigBallExecuId);

//最终的聚合活动"play over"等到了它的最后一个流入转移后,流向了end活动,所以流程实例结束

//因此可以断言此流程已经不存在了.
assertNull("execution"+pid+"应该不存在了",executionService.findExecutionById(pid));
System.out.println("结束了");
}

}

Fork-join活动看似其实不难,但是当流程变多的时候,我感觉在写代码的时候容易弄混淆,比如,流程在某个阶段执行到哪儿了,该怎样启动下一个流程,甚至有时候感觉有的state根本不需要,不知道其他人是否这样的感觉,但是我要说的是,假如真的能够体会你自己业务的每一步骤的话,就不会出现这种混乱的思想,举个简单的例子:假如有这样一个逻辑,某一个订单在发货后,1,客户要接收,2厂家要收款。这两个活动都完成了,那么才能结束流程,首先,你应该这样去考虑它们的步骤:发订单——》客户接收——客户打钱——厂家收款——销账(完成)。假如把这个过程再细化的话,首先发完订单,客户处于待接收状态,货到后客户可以接收,就变成待打钱状态,此时厂家就处于待收款状态,厂家收款后,销账完成。而这个细化的过程即基于每个状态点(如待接收状态),然后激起流程转移的动作(如接收),使我们真正在处理流程的过程。由于篇幅原因,下一张再介绍end等活动。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值