Commit 1d463f4f1a359f4a91cc07772c39f68008a69b89

Authored by jason
1 parent 91f356fc

fix: 修复回退报错问题, moveExecutionsToSingleActivityId 替换为 moveActivityIdsToSingleActivityId

yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
@@ -66,8 +66,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @@ -66,8 +66,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
66 66
67 @Override 67 @Override
68 protected void taskAssigned(FlowableEngineEntityEvent event) { 68 protected void taskAssigned(FlowableEngineEntityEvent event) {
69 - Task entity = (Task) event.getEntity();  
70 - FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskAssigned(entity)); 69 + taskService.processTaskAssigned((Task) event.getEntity());
71 } 70 }
72 71
73 @Override 72 @Override
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
@@ -917,7 +917,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -917,7 +917,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
917 * @param reqVO 前端参数封装 917 * @param reqVO 前端参数封装
918 */ 918 */
919 public void returnTask(Long userId, BpmnModel bpmnModel, Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) { 919 public void returnTask(Long userId, BpmnModel bpmnModel, Task currentTask, FlowElement targetElement, BpmTaskReturnReqVO reqVO) {
920 - // 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveActivityIdsToSingleActivityId 回撤 920 + // 1. 获得所有需要回撤的任务 taskDefinitionKey,用于稍后的 moveExecutionsToSingleActivityId 回撤
921 // 1.1 获取所有正常进行的任务节点 Key 921 // 1.1 获取所有正常进行的任务节点 Key
922 List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list(); 922 List<Task> taskList = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).list();
923 List<String> runTaskKeyList = convertList(taskList, Task::getTaskDefinitionKey); 923 List<String> runTaskKeyList = convertList(taskList, Task::getTaskDefinitionKey);
@@ -925,14 +925,16 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -925,14 +925,16 @@ public class BpmTaskServiceImpl implements BpmTaskService {
925 // 为什么不直接使用 runTaskKeyList 呢?因为可能存在多个审批分支,例如说:A -> B -> C 和 D -> F,而只要 C 撤回到 A,需要排除掉 F 925 // 为什么不直接使用 runTaskKeyList 呢?因为可能存在多个审批分支,例如说:A -> B -> C 和 D -> F,而只要 C 撤回到 A,需要排除掉 F
926 List<UserTask> returnUserTaskList = BpmnModelUtils.iteratorFindChildUserTasks(targetElement, runTaskKeyList, null, null); 926 List<UserTask> returnUserTaskList = BpmnModelUtils.iteratorFindChildUserTasks(targetElement, runTaskKeyList, null, null);
927 List<String> returnTaskKeyList = convertList(returnUserTaskList, UserTask::getId); 927 List<String> returnTaskKeyList = convertList(returnUserTaskList, UserTask::getId);
928 - 928 + List<String> runExecutionIds = new ArrayList<>();
929 // 2. 给当前要被退回的 task 数组,设置退回意见 929 // 2. 给当前要被退回的 task 数组,设置退回意见
930 taskList.forEach(task -> { 930 taskList.forEach(task -> {
931 // 需要排除掉,不需要设置退回意见的任务 931 // 需要排除掉,不需要设置退回意见的任务
932 if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) { 932 if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) {
933 return; 933 return;
934 } 934 }
935 - 935 + if (task.getExecutionId() != null) {
  936 + runExecutionIds.add(task.getExecutionId());
  937 + }
936 // 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务 938 // 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务
937 if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记 939 if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记
938 // 2.1.1 添加评论 940 // 2.1.1 添加评论
@@ -953,9 +955,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -953,9 +955,12 @@ public class BpmTaskServiceImpl implements BpmTaskService {
953 // 相关 issue: https://github.com/flowable/flowable-engine/issues/3944 955 // 相关 issue: https://github.com/flowable/flowable-engine/issues/3944
954 // ② flowable 7.2.0 版本后,继续使用 moveActivityIdsToSingleActivityId 方法。原因:flowable 7.2.0 版本修复了该问题。 956 // ② flowable 7.2.0 版本后,继续使用 moveActivityIdsToSingleActivityId 方法。原因:flowable 7.2.0 版本修复了该问题。
955 // 相关 issue:https://github.com/YunaiV/ruoyi-vue-pro/issues/1018 957 // 相关 issue:https://github.com/YunaiV/ruoyi-vue-pro/issues/1018
  958 + // ③ moveActivityIdsToSingleActivityId 使用遇到问题, 相关 issue https://gitee.com/zhijiantianya/yudao-cloud/issues/IJM8MS
  959 + // 改成 moveExecutionsToSingleActivityId 好像并没有遇到 ② 提到的超时提醒失效的问题。暂时先改回 moveExecutionsToSingleActivityId
  960 + // 目前还有的相关问题 https://t.zsxq.com/z4d9i。 估计需要升级 flowable 8 版本试试
956 runtimeService.createChangeActivityStateBuilder() 961 runtimeService.createChangeActivityStateBuilder()
957 .processInstanceId(currentTask.getProcessInstanceId()) 962 .processInstanceId(currentTask.getProcessInstanceId())
958 - .moveActivityIdsToSingleActivityId(returnTaskKeyList, reqVO.getTargetTaskDefinitionKey()) 963 + .moveExecutionsToSingleActivityId(runExecutionIds, reqVO.getTargetTaskDefinitionKey())
959 // 设置需要预测的任务 ids 的流程变量,用于辅助预测 964 // 设置需要预测的任务 ids 的流程变量,用于辅助预测
960 .processVariable(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskDefinitionKeys) 965 .processVariable(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_NEED_SIMULATE_TASK_IDS, needSimulateTaskDefinitionKeys)
961 // 设置流程变量节点退回标记, 用于退回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略,导致自动通过 966 // 设置流程变量节点退回标记, 用于退回到节点,不执行 BpmUserTaskAssignStartUserHandlerTypeEnum 策略,导致自动通过
@@ -1465,107 +1470,107 @@ public class BpmTaskServiceImpl implements BpmTaskService { @@ -1465,107 +1470,107 @@ public class BpmTaskServiceImpl implements BpmTaskService {
1465 log.error("[processTaskAssigned][taskId({}) 没有找到流程实例]", task.getId()); 1470 log.error("[processTaskAssigned][taskId({}) 没有找到流程实例]", task.getId());
1466 return; 1471 return;
1467 } 1472 }
1468 -  
1469 - // 自动去重,通过自动审批的方式  
1470 - BpmProcessDefinitionInfoDO processDefinitionInfo = bpmProcessDefinitionService.getProcessDefinitionInfo(task.getProcessDefinitionId());  
1471 - if (processDefinitionInfo == null) {  
1472 - log.error("[processTaskAssigned][taskId({}) 没有找到流程定义({})]", task.getId(), task.getProcessDefinitionId());  
1473 - return;  
1474 - }  
1475 - if (processDefinitionInfo.getAutoApprovalType() != null) {  
1476 - HistoricTaskInstanceQuery sameAssigneeQuery = historyService.createHistoricTaskInstanceQuery()  
1477 - .processInstanceId(task.getProcessInstanceId())  
1478 - .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus())  
1479 - .finished();  
1480 - if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType())  
1481 - && sameAssigneeQuery.taskAssignee(task.getAssignee()).count() > 0) {  
1482 - getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())  
1483 - .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName())); 1473 + // 需要基于 instance 设置租户编号,避免 Flowable 内部异步执行时【例如:超时自动通过】 丢失租户编号
  1474 + FlowableUtils.execute(processInstance.getTenantId(), () -> {
  1475 + // 自动去重,通过自动审批的方式
  1476 + BpmProcessDefinitionInfoDO processDefinitionInfo = bpmProcessDefinitionService.getProcessDefinitionInfo(task.getProcessDefinitionId());
  1477 + if (processDefinitionInfo == null) {
  1478 + log.error("[processTaskAssigned][taskId({}) 没有找到流程定义({})]", task.getId(), task.getProcessDefinitionId());
1484 return; 1479 return;
1485 } 1480 }
1486 - // 连续审批的节点自动通过  
1487 - if (BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getType().equals(processDefinitionInfo.getAutoApprovalType())) {  
1488 - BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());  
1489 - if (bpmnModel == null) {  
1490 - log.error("[processTaskAssigned][taskId({}) 没有找到流程模型({})]", task.getId(), task.getProcessDefinitionId());  
1491 - return;  
1492 - }  
1493 - List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingUserTaskFlows( // 获取所有的上一个 UserTask 节点连线  
1494 - BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())),  
1495 - SequenceFlow::getSourceRef);  
1496 - // 设置 taskIds, 并按创建时间倒序排序  
1497 - sameAssigneeQuery.taskDefinitionKeys(sourceTaskIds)  
1498 - .orderByTaskCreateTime()  
1499 - .desc();  
1500 - HistoricTaskInstance firstHisTask = CollUtil.getFirst(sameAssigneeQuery.list());  
1501 - if (firstHisTask != null && StrUtil.equals(firstHisTask.getAssignee(), task.getAssignee())) { 1481 + if (processDefinitionInfo.getAutoApprovalType() != null) {
  1482 + HistoricTaskInstanceQuery sameAssigneeQuery = historyService.createHistoricTaskInstanceQuery()
  1483 + .processInstanceId(task.getProcessInstanceId())
  1484 + .taskVariableValueEquals(BpmnVariableConstants.TASK_VARIABLE_STATUS, BpmTaskStatusEnum.APPROVE.getStatus())
  1485 + .finished();
  1486 + if (BpmAutoApproveTypeEnum.APPROVE_ALL.getType().equals(processDefinitionInfo.getAutoApprovalType())
  1487 + && sameAssigneeQuery.taskAssignee(task.getAssignee()).count() > 0) {
1502 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) 1488 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
1503 - .setReason(BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getName())); 1489 + .setReason(BpmAutoApproveTypeEnum.APPROVE_ALL.getName()));
1504 return; 1490 return;
1505 } 1491 }
  1492 + // 连续审批的节点自动通过
  1493 + if (BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getType().equals(processDefinitionInfo.getAutoApprovalType())) {
  1494 + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());
  1495 + if (bpmnModel == null) {
  1496 + log.error("[processTaskAssigned][taskId({}) 没有找到流程模型({})]", task.getId(), task.getProcessDefinitionId());
  1497 + return;
  1498 + }
  1499 + List<String> sourceTaskIds = convertList(BpmnModelUtils.getElementIncomingUserTaskFlows( // 获取所有的上一个 UserTask 节点连线
  1500 + BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey())),
  1501 + SequenceFlow::getSourceRef);
  1502 + // 设置 taskIds, 并按创建时间倒序排序
  1503 + sameAssigneeQuery.taskDefinitionKeys(sourceTaskIds)
  1504 + .orderByTaskCreateTime()
  1505 + .desc();
  1506 + HistoricTaskInstance firstHisTask = CollUtil.getFirst(sameAssigneeQuery.list());
  1507 + if (firstHisTask != null && StrUtil.equals(firstHisTask.getAssignee(), task.getAssignee())) {
  1508 + getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
  1509 + .setReason(BpmAutoApproveTypeEnum.APPROVE_SEQUENT.getName()));
  1510 + return;
  1511 + }
  1512 + }
1506 } 1513 }
1507 - }  
1508 1514
1509 - // 获取发起人节点  
1510 - BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());  
1511 - if (bpmnModel == null) {  
1512 - log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId());  
1513 - return;  
1514 - }  
1515 - FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());  
1516 - // 判断是否为退回或者驳回:如果是退回或者驳回不走这个策略  
1517 - Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(),  
1518 - String.format(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class);  
1519 - Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(),  
1520 - BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class));  
1521 - if (userTaskElement.getId().equals(START_USER_NODE_ID)  
1522 - && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核  
1523 - || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核  
1524 - && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {  
1525 - getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())  
1526 - .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason()));  
1527 - return;  
1528 - }  
1529 - // 当不为发起人节点时,审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理  
1530 - if (ObjectUtil.notEqual(userTaskElement.getId(), START_USER_NODE_ID)  
1531 - && StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) {  
1532 - if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {  
1533 - Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement);  
1534 -  
1535 - // 情况一:自动跳过  
1536 - if (ObjectUtils.equalsAny(assignStartUserHandlerType,  
1537 - BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType())) {  
1538 - getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())  
1539 - .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP.getReason()));  
1540 - return;  
1541 - }  
1542 - // 情况二:转交给部门负责人审批  
1543 - if (ObjectUtils.equalsAny(assignStartUserHandlerType,  
1544 - BpmUserTaskAssignStartUserHandlerTypeEnum.TRANSFER_DEPT_LEADER.getType())) {  
1545 - AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));  
1546 - Assert.notNull(startUser, "提交人({})信息为空", processInstance.getStartUserId());  
1547 - DeptRespDTO dept = startUser.getDeptId() != null ? deptApi.getDept(startUser.getDeptId()) : null;  
1548 - Assert.notNull(dept, "提交人({})部门({})信息为空", processInstance.getStartUserId(), startUser.getDeptId());  
1549 - // 找不到部门负责人的情况下,自动审批通过  
1550 - // noinspection DataFlowIssue  
1551 - if (dept.getLeaderUserId() == null) { 1515 + // 获取发起人节点
  1516 + BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());
  1517 + if (bpmnModel == null) {
  1518 + log.error("[processTaskAssigned][taskId({}) 没有找到流程模型]", task.getId());
  1519 + return;
  1520 + }
  1521 + FlowElement userTaskElement = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey());
  1522 + // 判断是否为退回或者驳回:如果是退回或者驳回不走这个策略
  1523 + Boolean returnTaskFlag = runtimeService.getVariable(processInstance.getProcessInstanceId(),
  1524 + String.format(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_RETURN_FLAG, task.getTaskDefinitionKey()), Boolean.class);
  1525 + Boolean skipStartUserNodeFlag = Convert.toBool(runtimeService.getVariable(processInstance.getProcessInstanceId(),
  1526 + BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class));
  1527 + if (userTaskElement.getId().equals(START_USER_NODE_ID)
  1528 + && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核
  1529 + || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核
  1530 + && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
  1531 + getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
  1532 + .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason()));
  1533 + return;
  1534 + }
  1535 + // 当不为发起人节点时,审批人与提交人为同一人时,根据 BpmUserTaskAssignStartUserHandlerTypeEnum 策略进行处理
  1536 + if (ObjectUtil.notEqual(userTaskElement.getId(), START_USER_NODE_ID)
  1537 + && StrUtil.equals(task.getAssignee(), processInstance.getStartUserId())) {
  1538 + if (ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) {
  1539 + Integer assignStartUserHandlerType = BpmnModelUtils.parseAssignStartUserHandlerType(userTaskElement);
  1540 +
  1541 + // 情况一:自动跳过
  1542 + if (ObjectUtils.equalsAny(assignStartUserHandlerType,
  1543 + BpmUserTaskAssignStartUserHandlerTypeEnum.SKIP.getType())) {
1552 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) 1544 getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
1553 - .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND.getReason())); 1545 + .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP.getReason()));
1554 return; 1546 return;
1555 } 1547 }
1556 - // 找得到部门负责人的情况下,修改负责人  
1557 - if (ObjectUtil.notEqual(dept.getLeaderUserId(), startUser.getId())) {  
1558 - getSelf().transferTask(Long.valueOf(task.getAssignee()), new BpmTaskTransferReqVO()  
1559 - .setId(task.getId()).setAssigneeUserId(dept.getLeaderUserId())  
1560 - .setReason(BpmReasonEnum.ASSIGN_START_USER_TRANSFER_DEPT_LEADER.getReason()));  
1561 - return; 1548 + // 情况二:转交给部门负责人审批
  1549 + if (ObjectUtils.equalsAny(assignStartUserHandlerType,
  1550 + BpmUserTaskAssignStartUserHandlerTypeEnum.TRANSFER_DEPT_LEADER.getType())) {
  1551 + AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
  1552 + Assert.notNull(startUser, "提交人({})信息为空", processInstance.getStartUserId());
  1553 + DeptRespDTO dept = startUser.getDeptId() != null ? deptApi.getDept(startUser.getDeptId()) : null;
  1554 + Assert.notNull(dept, "提交人({})部门({})信息为空", processInstance.getStartUserId(), startUser.getDeptId());
  1555 + // 找不到部门负责人的情况下,自动审批通过
  1556 + // noinspection DataFlowIssue
  1557 + if (dept.getLeaderUserId() == null) {
  1558 + getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId())
  1559 + .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_DEPT_LEADER_NOT_FOUND.getReason()));
  1560 + return;
  1561 + }
  1562 + // 找得到部门负责人的情况下,修改负责人
  1563 + if (ObjectUtil.notEqual(dept.getLeaderUserId(), startUser.getId())) {
  1564 + getSelf().transferTask(Long.valueOf(task.getAssignee()), new BpmTaskTransferReqVO()
  1565 + .setId(task.getId()).setAssigneeUserId(dept.getLeaderUserId())
  1566 + .setReason(BpmReasonEnum.ASSIGN_START_USER_TRANSFER_DEPT_LEADER.getReason()));
  1567 + return;
  1568 + }
  1569 + // 如果部门负责人是自己,还是自己审批吧~
1562 } 1570 }
1563 - // 如果部门负责人是自己,还是自己审批吧~  
1564 } 1571 }
1565 } 1572 }
1566 - }  
1567 - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号  
1568 - FlowableUtils.execute(processInstance.getTenantId(), () -> { 1573 +
1569 AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId())); 1574 AdminUserRespDTO startUser = adminUserApi.getUser(Long.valueOf(processInstance.getStartUserId()));
1570 messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task)); 1575 messageService.sendMessageWhenTaskAssigned(BpmTaskConvert.INSTANCE.convert(processInstance, startUser, task));
1571 }); 1576 });