【工作流Activiti7】4、Activiti7 结束/终止流程

1.  结束/终止 正在运行的流程实例

思路:跟回退一样的思路一样,直接从当前节点跳到结束节点(EndEvent) 

/**
 * 结束任务
 * @param taskId    当前任务ID
 */
public void endTask(String taskId) {
    //  当前任务
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

    BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
    List endEventList = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class);
    FlowNode endFlowNode = endEventList.get(0);
    FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());

    //  临时保存当前活动的原始方向
    List originalSequenceFlowList = new ArrayList<>();
    originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
    //  清理活动方向
    currentFlowNode.getOutgoingFlows().clear();

    //  建立新方向
    SequenceFlow newSequenceFlow = new SequenceFlow();
    newSequenceFlow.setId("newSequenceFlowId");
    newSequenceFlow.setSourceFlowElement(currentFlowNode);
    newSequenceFlow.setTargetFlowElement(endFlowNode);
    List newSequenceFlowList = new ArrayList<>();
    newSequenceFlowList.add(newSequenceFlow);
    //  当前节点指向新的方向
    currentFlowNode.setOutgoingFlows(newSequenceFlowList);

    //  完成当前任务
    taskService.complete(task.getId());

    //  可以不用恢复原始方向,不影响其它的流程
//        currentFlowNode.setOutgoingFlows(originalSequenceFlowList);
}

补充1:关于BUSINESS_KEY_

BUSINESS_KEY_ 字段是用于将业务系统与Actititi工作流关联的关键字段,通常我们用它来存放业务表的ID,比如:请假ID、报销ID等等。

但是,通常咱们系统不可能只有一个流程,假设我们做的是一个OA系统,那么公司的流程有请假、采购、报销等等流程,那这一个字段如何区分到底是哪个业务流程的ID呢,换言之,假设BUSINESS_KEY_这个字段现在是2,那么我怎么知道这个2是请假表的ID,还是采购表的ID呢?因此,要想通过这个一个字段区分不同的类型就要求这个字段是唯一的,比如我们可以加上业务标识,比如:holiday:2,purchase:3等等。还有一种方式,利用另外一个空闲字段TENANT_ID_,我们可以把业务类型存到TENANT_ID_字段中,这样TENANT_ID_和BUSINESS_KEY_两个字段就能唯一确定是哪个业务的那个ID。

/**
 * 7.1.0.M6的act_ru_task表中有BUSINESS_KEY_字段,因此可以直接task.getBusinessKey()
 * 而7.1.0.M5中没有这个字段,因此要想获取BUSINESS_KEY_必须从act_ru_execution表中取
 */
@Test
public void testBusinessKey() {
    List<Task> taskList = taskService.createTaskQuery().taskCandidateOrAssigned("lisi").taskTenantId("11").list();
    Set<String> processInstanceIds = taskList.stream().map(Task::getProcessInstanceId).collect(Collectors.toSet());
    List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list();
    
    List<String> businessKeyList = processInstances.stream().map(ProcessInstance::getBusinessKey).collect(Collectors.toList());
    System.out.println(businessKeyList);

    Pattern pattern = Pattern.compile("^(\\w+):(\\d+)$");
    
    List<Integer> businessIds = new ArrayList<>();
    businessKeyList.forEach(businessKey->{
        Matcher matcher = pattern.matcher(businessKey);
        if (matcher.find()) {
            String id = matcher.group(2);
            businessIds.add(Integer.valueOf(id));
        }
    });
}

补充2:Activiti不同版本的Bug

首先,我发现不同版本的表结构不一样,当用 7.1.0.M5 版本时,启动就报错,缺少字段

org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
### The error may exist in org/activiti/db/mapping/entity/Deployment.xml
### The error may involve org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl.insertDeployment-Inline
### The error occurred while setting parameters
### SQL: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_, VERSION_, PROJECT_RELEASE_VERSION_)     values(?, ?, ?, ?, ?, ?, ?, ?, ?)
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) ~[mybatis-3.5.0.jar:3.5.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200) ~[mybatis-3.5.0.jar:3.5.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) ~[mybatis-3.5.0.jar:3.5.0]
    at org.activiti.engine.impl.db.DbSqlSession.flushRegularInsert(DbSqlSession.java:787) ~[activiti-engine-7.1.0.M5.jar:na]
    at org.activiti.engine.impl.db.DbSqlSession.flushInsertEntities(DbSqlSession.java:662) ~[activiti-engine-7.1.0.M5.jar:na]
    at org.activiti.engine.impl.db.DbSqlSession.flushInserts(DbSqlSession.java:642) ~[activiti-engine-7.1.0.M5.jar:na]
    at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:525) ~[activiti-engine-7.1.0.M5.jar:na]

解决办法也很简单,将缺失的字段加上即可:

ALTER TABLE `act_re_deployment` 
ADD COLUMN `VERSION_` int(11) NULL DEFAULT NULL,
ADD COLUMN `PROJECT_RELEASE_VERSION_` varchar(255) NULL DEFAULT NULL;

其次,我发现在启动流程实例查询流程定义时,7.1.0.M5是按版本升序取第一个,而7.1.0.M6是降序

同时,还发现7.1.0.M6有一个明显的Bug,这个Bug会导致当有多个部署的时候,即当act_re_deployment表中的记录多于1条时,就无法使用processRuntime.start()启动流程实例

本着用新不用旧的原则,还是建议用7.1.0.M6

还有一个bug,这个bug发生在当使用原生的taskService完成任务时,多次设置同一个流程变量的值后者不会覆盖前者。即,ACT_RU_VARIABLE表中变量的值没有更新。

为了说明这个问题,看下面这个图:

节点“1”完成任务时设置result==3,于是后面的流程永远是1->3->1->3->...  ,即使下一次执行时result==1,流程也不会走到2。经过分析,我猜测对同一个变量多次赋值,后者没有覆盖前者,也就是说第2次赋值没有生效,查看ACT_RU_VARIABLE表果然是这样,变量的值没有更新。经过反复试验,我发现用taskRuntime.complete()完成任务时就不会出现这个问题,流程变量的值会正常更新。


Map<String, Object> variables = new HashMap<>();
variables.put("result", 3);

//	这样写的话,多次对同一个流程变量赋值时,流程变量的值不会更新,即后面的赋值永远是不生效的
Task task = taskService.createTaskQuery().taskId("1234").singleResult();
taskService.complete(task.getId(), variables);

//	这样写的话,就很完美,ACT_RU_VARIABLE表的流程变量的值正常更新
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId("1234").withVariables(variables).build());

补充3:任务监听器

@Slf4j
@Component
public class TaskCreateListener implements TaskRuntimeEventListener<TaskCreatedEvent> {
    @Override
    public void onEvent(TaskCreatedEvent event) {
    	System.out.println("任务被创建");
    }
}

@Slf4j
@Component
public class TaskAssignedListener implements TaskRuntimeEventListener<TaskAssignedEvent> {
    @Override
    public void onEvent(TaskAssignedEvent event) {
	System.out.println("任务被指派");
    }
}

@Slf4j
@Component
public class TaskCompletedListener implements TaskRuntimeEventListener<TaskCompletedEvent> {
    @Override
    public void onEvent(TaskCompletedEvent event) {
	System.out.println("任务被完成");
    }
}

### 回答1: Activiti是一个开源的工作流引擎,它提供了丰富的API来帮助开发人员设计和管理工作流程。Activiti 7是Activiti的最新版本,它提供了许多新的功能和改进,包括更好的性能和易用性。Activiti API可以用来管理工作流程定义、部署和执行,包括启动、查询和终止流程实例。此外,Activiti API还提供了对流程变量、任务和历史数据的管理功能。 ### 回答2: activiti7是一个开源的工作流引擎,它是activiti的升级版本。activiti7提供了一套强大的API,使得开发者可以方便地与工作流引擎进行交互。 activiti7的API可以用于各种工作流相关的操作,包括流程定义、流程实例、任务管理等。通过activiti7的API,开发者可以创建、部署和管理各种流程定义,定义流程的图形模型、表单等。同时,API还支持启动、暂停和终止流程实例,查询和处理任务,得到流程实例运行状态等。 使用activiti7的API还可以对流程进行管理,包括监听流程启动、流程完成等事件,触发相应的业务逻辑。此外,API还支持获取和设置流程变量,进行用户组和角色的管理,以及集成和扩展其他业务系统等。 activiti7的API遵循了RESTful架构,提供了一套统一的HTTP接口,使得开发者可以轻松地集成activiti7到自己的应用程序中。同时,activiti7还提供了一些Java类库和工具类,方便开发者进行各种操作。 总之,activiti7提供了一套简洁易用的API,使得开发者可以方便地使用工作流引擎,实现各种复杂的工作流业务。无论是开发者还是企业用户,都可以通过activiti7的API来提升工作效率和业务管理能力。 ### 回答3: Activiti7是一个开源的企业级工作流管理和自动化平台,它提供了一套强大的API,用于流程定义、任务管理、流程实例管理等操作。 首先,使用Activiti7的API可以定义流程,包括流程节点、流程变量和流程规则等。可以使用API中的类和方法创建和配置流程,将各个节点按照需要连接起来,并定义流程中的变量和规则。通过API的调用,可以实现灵活的流程定义,满足业务需求。 其次,Activiti7的API还提供了任务管理功能。通过API可以创建、分配和处理任务,可以将任务分配给特定的用户或组,并设置任务的截止日期和优先级等属性。API还提供了查询任务的方法,可以根据不同的条件查询任务列表,并对任务进行处理,如完成、取消或重新指派任务等。 另外,API还包括流程实例管理的功能。通过API可以启动流程实例,跟踪流程实例的状态,并对流程实例进行操作,如暂停、恢复或终止。API还提供了查询流程实例的方法,可以根据条件查询流程实例列表,并对流程实例进行管理和监控。 总结来说,Activiti7提供了一套功能丰富的API,可以方便地进行流程定义、任务管理和流程实例管理。通过使用这些API,可以实现灵活、高效的工作流管理和自动化,提升企业的业务流程效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟是大神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值