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

news/2024/5/10 4:30:53/文章来源:https://blog.csdn.net/wufaqidong1/article/details/128427092

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> {@Overridepublic void onEvent(TaskCreatedEvent event) {System.out.println("任务被创建");}
}@Slf4j
@Component
public class TaskAssignedListener implements TaskRuntimeEventListener<TaskAssignedEvent> {@Overridepublic void onEvent(TaskAssignedEvent event) {System.out.println("任务被指派");}
}@Slf4j
@Component
public class TaskCompletedListener implements TaskRuntimeEventListener<TaskCompletedEvent> {@Overridepublic void onEvent(TaskCompletedEvent event) {System.out.println("任务被完成");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_616877.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

02:损失函数总结

目录 nn.L1Loss: nn.NLLLoss: nn.MSELoss: nn.CrossEntropyLoss: 损失函数是用来估量模型的预测值与真实值的不一致程度&#xff0c;它是一个非负实值函数。我们训练模型的过程&#xff0c;就是通过不断的迭代计算&#xff0c;使用梯度下降的优化算法&#xff0c;使得损失函…

为什么编程入门从Python学起?

目前&#xff0c;青岛市的小学、初中、高中对于编程教育和信息学的推进几乎都选中了Python。 浙江省新高中信息技术教材改革项目中&#xff0c;高中新生开始使用新教材&#xff0c;里面的编程语言将换用 Python&#xff0c;Python 将正式纳入高考内容。 Python是一种代表简单主…

【综合】简单加解密——寻找序列号

【综合】简单加解密——寻找序列号 下面文字对你可能有用(复制粘贴): #include <stdlib.h> #include <string.h> #include “malloc.h” #define MaxPass 66 // 最多66段密文 #define NumbPwdTable 5 // 密码表的份数 #define SizePwdTable 0x210 // 每份密码表占…

雷军主导小米管理层变革:创业派隐退 职业经理人上位

雷递网 雷建平 12月23日岁末之际&#xff0c;在京东零售大幅调整后&#xff0c;小米也进行了一轮大调整。小米集团内部邮件所示&#xff0c;小米总裁王翔将在月底卸任集团总裁职务退休&#xff0c;同时&#xff0c;继续作为高级顾问为公司服务。小米集团总裁一职将由2019年加入…

互联网行业逐步回暖!就业显示有74%学员跨专业学编程!

三年以来&#xff0c;居家办公、隔离等影响已深入每个人的生活。就业形势承受着巨大的压力&#xff0c;同时就业环境也发生巨大变化&#xff0c;越来越多的人都面临转行&#xff01; 达妹被问到最多的问题是&#xff1a; 跨专业学编程的疑虑 非科班出身零基础能学会编程吗? 数…

【源码共读】Vue2 中为什么可以使用 this 访问各种选项中的属性?

如何阅读源码 网上有很多关于源码阅读的文章&#xff0c;每个人都有自己的方式&#xff0c;但是网上的文章都是精炼之后的&#xff0c;告诉你哪个文件、那个函数、那个变量是干什么的&#xff1b; 但是没有告诉你这些是怎么找到的&#xff0c;这些是怎么理解的&#xff0c;这…

基于Vue+SpringBoot智慧校园疫情防控系统(PC端、手机端)--附源码

介绍 智慧校园疫情防控系统——PC 手机端 多端并行 项目源码下载&#xff1a;https://download.csdn.net/download/DeepLearning_/87340321 软件架构 手机端信息系统——日常健康信息填报系统&#xff08;前端手机端 文件夹&#xff09;电脑端智疫图 —— 数据可视化界面 &…

前端(htmlCSSJavaScript)基础

关于前端更多知识请关注官网&#xff1a;w3school 在线教程全球最大的中文 Web 技术教程。https://www.w3school.com.cn/ 1.HTML HTML(HyperText Markup Language)&#xff1a;超文本标记语言 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大。除了文字信息…

嘿ChatGPT,来帮我写代码

最近 ChatGPT 发行了&#xff0c;这是由 OpenAI 开发的AI聊天机器人&#xff0c;专门研究对话。它的目标是使AI系统更自然地与之互动&#xff0c;但是在编写代码时也可以为您提供帮助。您可以让 ChatGPT 做你的编程助理&#xff0c;甚至更多&#xff01;在过去的几天里&#xf…

小布助手,身入大千世界

在2018年—2019年&#xff0c;AI智能助手一度火热&#xff0c;成了科技行业的全新风口。智能音箱与手机中&#xff0c;我们能看到各种各样的智能助手横空出世&#xff0c;一度成为产品标配。但随着时间缓缓冲刷&#xff0c;就像所有科技风口一样&#xff0c;有的AI智能助手随着…

可以做抽奖活动的微信小程序在哪里做_分享抽奖活动小程序制作步骤

越来越多的企业开始了解微信抽奖游戏的实用性和价值&#xff0c;因为用户更喜欢简单有趣的游戏抽奖方式&#xff0c;如大转盘、摇一摇、抢福袋、砸金蛋、摇一摇、刮刮卡等互动抽奖游戏。 如果企业想制作这种抽奖游戏&#xff0c;都倾向使用市场上的各种抽奖制作软件&#xff0c…

Bloom filter-based AQM 和 BBR 公平性

设 B 为 Delivery rate&#xff0c;D 为 Delay&#xff0c;将 E B/D 作为衡量效能&#xff0c;所有流量的收敛状态是一个 Nash 均衡&#xff0c;没有任何流量有动机增加或者减少 inflight。参见&#xff1a;更合理的 BBR。 并不是都知道这道理&#xff0c;增加 inflight 能挤…

【Java 数据结构】-二叉树OJ题

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的博客&#x1f319; 专栏&#xff1a;【Java 数据结构】 分享&#xff1a;宇宙的最可理解之处在于它是不可理解的&#xff0c;宇宙的最不可理解之处在于它是可理解的。——《乡村教师》 主要内容&#xff1a;二叉树的…

一维树状数组

引入 树状数组和线段树具有相似的功能&#xff0c;但他俩毕竟还有一些区别&#xff1a;树状数组能有的操作&#xff0c;线段树一定有&#xff1b;线段树有的操作&#xff0c;树状数组不一定有。但是树状数组的代码要比线段树短&#xff0c;思维更清晰&#xff0c;速度也更快&a…

雷神科技在北交所上市首日破发:上半年业绩下滑,路凯林为董事长

12月23日&#xff0c;青岛雷神科技股份有限公司&#xff08;下称“雷神科技”&#xff0c;BJ:872190&#xff09;在北京证券交易所&#xff08;即北交所&#xff09;上市。本次上市&#xff0c;雷神科技的发行价为25.00元/股&#xff0c;发行数量为1250万股&#xff0c;发行后总…

目标检测之Fast RCNN概述

基本原理 Fast Rcnn主要步骤为 利用SR算法生成候选区域利用VGG16网络进行特征提取利用第一步生成的候选区域在特征图中得到对应的特征矩阵利用ROI pooling将特征矩阵缩放到相同大小并平展得到预测结果 相对于RCNN的优化 主要有三个改进 不再将每一个候选区域依次放入CNN网络…

el-Dropdown 两个下拉框之间的动态绑定 实现默认选中值

目录 业务场景 官方链接 实现效果 使用框架 代码展示 template代码 script代码 变量定义 事件定义 onMounted事件 courseClass事件--课程班级绑定 defaultValue事件 optionChange事件 changeClass事件 为什么要给课程的每个选项也绑定click事件&#xff1f;作用是什么…

文字对称中的数学与魔术(二)——英文字母到单词的对称性

早点关注我&#xff0c;精彩不错过&#xff01;在上一篇文章中&#xff0c;我们引入了语言文字对称性这个领域&#xff0c;重点介绍了阿拉伯数字的对称性&#xff0c;相关内容请戳&#xff1a;文字对称中的数学与魔术&#xff08;一&#xff09;——阿拉伯数字的对称性今天我们…

el-pagination 动态切换每页条数、页数切换

目录 业务场景 官方链接 实现效果 使用框架 代码展示 template代码 script代码 变量定义 事件定义 handleSizeChange事件--实现每页条数改变表格动态变化 handleCurrentChange事件--切换页码 css代码 完整代码 总结 业务场景 当表格中的数据量如果非常庞大的时候我们…

2022-忙碌的一年

&#xff08;点击即可听音频&#xff09;前言花有重开日,人无再少年.每当这个时候,回头驻足,不是感慨万千,就是惜时如金,一年悄无声息的从指尖划过,星海横流,岁月如碑.那些被偷走的时光,发生了大大小小的事无论是平淡无奇,还是历久难忘,有惊喜,有遗憾,终将都会隐入尘烟。大到国…