From dee2b7cb96d7e7b3385c49301835ea503f74095f Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Mon, 24 Feb 2025 09:38:37 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix:=20=E4=BB=A3=E7=A0=81=E5=AE=A1=E6=9F=A5?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmSimpleModelNodeTypeEnum.java | 3 +- .../vo/model/simple/BpmSimpleModelNodeVO.java | 20 +++--- .../flowable/core/util/FlowableUtils.java | 5 +- .../flowable/core/util/SimpleModelUtils.java | 65 +++++++------------ .../task/BpmProcessInstanceServiceImpl.java | 7 +- .../bpm/service/task/BpmTaskServiceImpl.java | 2 +- .../listener/BpmCallActivityListener.java | 9 +-- 7 files changed, 43 insertions(+), 68 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java index b21bc65313..e5ffa12025 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java @@ -30,8 +30,7 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable { DELAY_TIMER_NODE(14, "延迟器", "receiveTask"), TRIGGER_NODE(15, "触发器", "serviceTask"), - CHILD_PROCESS(20, "子流程", "callActivity"), // TODO @lesan:CHILD_PROCESS、ASYNC_CHILD_PROCESS 可以合并为一个么? - ASYNC_CHILD_PROCESS(21, "异步子流程", "callActivity"), + CHILD_PROCESS(20, "子流程", "callActivity"), // 50 ~ 条件分支 CONDITION_NODE(50, "条件", "sequenceFlow"), // 用于构建流转条件的表达式 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index 2f36e3eecb..bc2c72898f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -425,33 +425,30 @@ public class BpmSimpleModelNodeVO { @Valid public static class ChildProcessSetting { - // TODO @lesan:calledElement => calledProcessDefinitionKey ? 这样更容易理解?不过如果一个流程多次发起,key 变了,好像会有问题? @Schema(description = "被调用流程", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxx") @NotEmpty(message = "被调用流程不能为空") - private String calledElement; + private String calledProcessDefinitionKey; @Schema(description = "被调用流程名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "xxx") @NotEmpty(message = "被调用流程名称不能为空") - private String calledElementName; + private String calledProcessDefinitionName; @Schema(description = "是否异步", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") @NotNull(message = "是否异步不能为空") private Boolean async; - // TODO @lesan:inVariables - @Schema(description = "输入参数(主->子)", requiredMode = Schema.RequiredMode.REQUIRED, example = "[]") - private List inVariable; + @Schema(description = "输入参数(主->子)", example = "[]") + private List inVariables; - // TODO @lesan:outVariables @Schema(description = "输出参数(子->主)", example = "[]") - private List outVariable; + private List outVariables; - @Schema(description = "是否自动跳过子流程发起节点", example = "false") + @Schema(description = "是否自动跳过子流程发起节点", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") @NotNull(message = "是否自动跳过子流程发起节点不能为空") private Boolean skipStartUserNode; @Schema(description = "子流程发起人配置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") - // TODO @lesan:这个应该也必须填写? + @NotNull(message = "子流程发起人配置不能为空") private StartUserSetting startUserSetting; @Schema(description = "子流程发起人配置") @@ -467,11 +464,10 @@ public class BpmSimpleModelNodeVO { @Schema(description = "表单", example = "xxx") private String formField; - // TODO @lesan:emptyHandleType => emptyType,和 type 对上? @Schema(description = "当子流程发起人为空时类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "当子流程发起人为空时类型不能为空") @InEnum(BpmChildProcessStartUserEmptyTypeEnum.class) - private Integer emptyHandleType; + private Integer emptyType; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java index 7ab71a0470..6022b8fe93 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/FlowableUtils.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -244,8 +244,7 @@ public class FlowableUtils { return formFieldsMap.entrySet().stream() .limit(3) .map(entry -> new KeyValue<>(entry.getValue().getTitle(), - // TODO @lesan: MapUtil.getStr 可以更简单? - StrUtil.toStringOrEmpty(processVariables.getOrDefault(entry.getValue().getField(), "")))) + MapUtil.getStr(processVariables, entry.getValue().getField(), ""))) .collect(Collectors.toList()); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 19c804a754..412f630f95 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -48,7 +48,7 @@ public class SimpleModelUtils { new StartUserNodeConvert(), new ApproveNodeConvert(), new CopyNodeConvert(), new TransactorNodeConvert(), new DelayTimerNodeConvert(), new TriggerNodeConvert(), new ConditionBranchNodeConvert(), new ParallelBranchNodeConvert(), new InclusiveBranchNodeConvert(), new RouteBranchNodeConvert(), - new ChildProcessConvert(), new AsyncChildProcessConvert()); + new ChildProcessConvert()); converts.forEach(convert -> NODE_CONVERTS.put(convert.getType(), convert)); } @@ -819,46 +819,38 @@ public class SimpleModelUtils { @Override public CallActivity convert(BpmSimpleModelNodeVO node) { BpmSimpleModelNodeVO.ChildProcessSetting childProcessSetting = node.getChildProcessSetting(); - List inVariable = childProcessSetting.getInVariable() == null ? - new ArrayList<>() : new ArrayList<>(childProcessSetting.getInVariable()); + List inVariables = childProcessSetting.getInVariables() == null ? + new ArrayList<>() : new ArrayList<>(childProcessSetting.getInVariables()); CallActivity callActivity = new CallActivity(); callActivity.setId(node.getId()); callActivity.setName(node.getName()); - callActivity.setCalledElementType("key"); // TODO @lesan:这里为啥是 key 哈? + callActivity.setCalledElementType("key"); // 1. 是否异步 - callActivity.setAsynchronous(node.getChildProcessSetting().getAsync()); - - // 2. 调用的子流程 - callActivity.setCalledElement(childProcessSetting.getCalledElement()); - callActivity.setProcessInstanceName(childProcessSetting.getCalledElementName()); - - // 3. 是否自动跳过子流程发起节点 - // TODO @lesan:貌似只有 SourceExpression 的区别,直接通过 valueOf childProcessSetting.getSkipStartUserNode()??? - if (Boolean.TRUE.equals(childProcessSetting.getSkipStartUserNode())) { - IOParameter ioParameter = new IOParameter(); - ioParameter.setSourceExpression("true"); - ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); - inVariable.add(ioParameter); - } else { - IOParameter ioParameter = new IOParameter(); - ioParameter.setSourceExpression("false"); - ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); - inVariable.add(ioParameter); + if (node.getChildProcessSetting().getAsync()) { + // TODO @lesan: 这里目前测试没有跳过执行call activity 后面的节点 + callActivity.setAsynchronous(true); } - // 4. 主→子变量传递 - // 4.1 【默认需要传递的一些变量】流程状态 - // TODO @lesan:4.1 这个要不,单独一个序号,类似 3. 这个。然后下面,就是把 主→子变量传递、子→主变量传递;这样逻辑连贯点哈 + // 2. 调用的子流程 + callActivity.setCalledElement(childProcessSetting.getCalledProcessDefinitionKey()); + callActivity.setProcessInstanceName(childProcessSetting.getCalledProcessDefinitionName()); + + // 3. 是否自动跳过子流程发起节点 IOParameter ioParameter = new IOParameter(); + ioParameter.setSourceExpression(childProcessSetting.getSkipStartUserNode().toString()); + ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE); + inVariables.add(ioParameter); + + // 4. 【默认需要传递的一些变量】流程状态 + ioParameter = new IOParameter(); ioParameter.setSource(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); ioParameter.setTarget(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); - inVariable.add(ioParameter); - callActivity.setInParameters(inVariable); + inVariables.add(ioParameter); - // 5. 子→主变量传递 - // TODO @lesan:通过 isNotEmpty 这种哈 - if (childProcessSetting.getOutVariable() != null && !childProcessSetting.getOutVariable().isEmpty()) { - callActivity.setOutParameters(childProcessSetting.getOutVariable()); + // 5. 主→子变量传递、子->主变量传递 + callActivity.setInParameters(inVariables); + if (ArrayUtil.isNotEmpty(childProcessSetting.getOutVariables()) && ObjUtil.notEqual(childProcessSetting.getAsync(), Boolean.TRUE)) { + callActivity.setOutParameters(childProcessSetting.getOutVariables()); } // 6. 子流程发起人配置 @@ -886,16 +878,6 @@ public class SimpleModelUtils { } - private static class AsyncChildProcessConvert extends ChildProcessConvert { - - @Override - public BpmSimpleModelNodeTypeEnum getType() { - return BpmSimpleModelNodeTypeEnum.ASYNC_CHILD_PROCESS; - } - - } - - private static String buildGatewayJoinId(String id) { return id + "_join"; } @@ -926,7 +908,6 @@ public class SimpleModelUtils { || nodeType == BpmSimpleModelNodeTypeEnum.TRANSACTOR_NODE || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS - || nodeType == BpmSimpleModelNodeTypeEnum.ASYNC_CHILD_PROCESS || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { // 添加元素 resultNodes.add(currentNode); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 558180dd3f..b5c9709bd1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -320,7 +320,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 遍历 tasks 列表,只处理已结束的 UserTask // 为什么不通过 activities 呢?因为,加签场景下,它只存在于 tasks,没有 activities,导致如果遍历 activities // 的话,它无法成为一个节点 - // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程;TODO @lesan:这个会有啥影响?微信聊? + // TODO @芋艿:子流程只有activity,这里获取不到已结束的子流程;TODO @lesan:这个会导致timeline不会展示已结束的子流程 List endTasks = filterList(tasks, task -> task.getEndTime() != null); List approvalNodes = convertList(endTasks, task -> { FlowElement flowNode = BpmnModelUtils.getFlowElementById(bpmnModel, task.getTaskDefinitionKey()); @@ -414,7 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 处理每个任务的 tasks 属性 for (HistoricActivityInstance activity : taskActivities) { HistoricTaskInstance task = taskMap.get(activity.getTaskId()); - // TODO @lesan:这里为啥 continue 哈? + // TODO @lesan:这里为啥 continue 哈? @芋艿:子流程的 activity 中 task 是null 下面的方法会报错 if (task == null) { continue; } @@ -510,8 +510,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService } // 4. 子流程节点 - if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(node.getType()) || - BpmSimpleModelNodeTypeEnum.ASYNC_CHILD_PROCESS.getType().equals(node.getType())) { + if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(node.getType())) { return activityNode; } return null; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index e91c7e8f35..8f59e6e99d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1230,7 +1230,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (userTaskElement.getId().equals(START_USER_NODE_ID) && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 || Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 - && !Boolean.TRUE.equals(returnTaskFlag)) { // TODO @lesan:ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE) 改成这个有问题么?尽量不用 ! 取反 + && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); return; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java index 2be4fcc8de..1c2d980380 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java @@ -59,19 +59,19 @@ public class BpmCallActivityListener implements ExecutionListener { // 2.1 当表单值为空时 if (StrUtil.isEmpty(formFieldValue)) { // 2.1.1 来自主流程发起人 - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { + if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_START_USER.getType())) { FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); return; } // 2.1.2 来自子流程管理员 - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())) { + if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.CHILD_PROCESS_ADMIN.getType())) { BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(execution.getProcessDefinitionId()); List managerUserIds = processDefinition.getManagerUserIds(); FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); return; } // 2.1.3 来自主流程管理员 - if (startUserSetting.getEmptyHandleType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { + if (startUserSetting.getEmptyType().equals(BpmChildProcessStartUserEmptyTypeEnum.MAIN_PROCESS_ADMIN.getType())) { BpmProcessDefinitionInfoDO processDefinition = processDefinitionService.getProcessDefinitionInfo(parent.getProcessDefinitionId()); List managerUserIds = processDefinition.getManagerUserIds(); FlowableUtils.setAuthenticatedUserId(managerUserIds.get(0)); @@ -82,7 +82,8 @@ public class BpmCallActivityListener implements ExecutionListener { try { FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue)); } catch (Exception e) { - // todo @lesan:打个日志,方便排查 + log.error("[error][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", + DELEGATE_EXPRESSION, formFieldValue); FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); } } From 15d0a11badab81b0338fac48d7b176e97bc93161 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Mon, 24 Feb 2025 15:30:15 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E5=AD=90=E6=B5=81=E7=A8=8B-?= =?UTF-8?q?=E8=B6=85=E6=97=B6=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../definition/BpmBoundaryEventTypeEnum.java | 3 ++- .../vo/model/simple/BpmSimpleModelNodeVO.java | 21 +++++++++++++++++ .../core/listener/BpmTaskEventListener.java | 3 +++ .../flowable/core/util/SimpleModelUtils.java | 23 +++++++++++++++++-- .../bpm/service/task/BpmTaskService.java | 8 +++++++ .../bpm/service/task/BpmTaskServiceImpl.java | 12 ++++++++++ 6 files changed, 67 insertions(+), 3 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java index a63804de32..69c5512599 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java @@ -14,7 +14,8 @@ import lombok.Getter; public enum BpmBoundaryEventTypeEnum { USER_TASK_TIMEOUT(1, "用户任务超时"), - DELAY_TIMER_TIMEOUT(2, "延迟器超时"); + DELAY_TIMER_TIMEOUT(2, "延迟器超时"), + CHILD_PROCESS_TIMEOUT(3, "子流程超时"); private final Integer type; private final String name; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index bc2c72898f..a85a75c160 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -451,6 +451,9 @@ public class BpmSimpleModelNodeVO { @NotNull(message = "子流程发起人配置不能为空") private StartUserSetting startUserSetting; + @Schema(description = "超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}") + private TimeoutSetting timeoutSetting; + @Schema(description = "子流程发起人配置") @Data @Valid @@ -471,5 +474,23 @@ public class BpmSimpleModelNodeVO { } + @Schema(description = "超时设置") + @Data + @Valid + public static class TimeoutSetting { + + @Schema(description = "是否开启超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") + @NotNull(message = "是否开启超时设置不能为空") + private Boolean enable; + + @Schema(description = "时间类型", example = "1") + @InEnum(BpmDelayTimerTypeEnum.class) + private Integer type; + + @Schema(description = "时间表达式", example = "PT1H,2025-01-01T00:00:00") + private String timeExpression; + + } + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java index bb256001b0..5f88987f28 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java @@ -110,6 +110,9 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT)) { String taskKey = boundaryEvent.getAttachedToRefId(); taskService.triggerReceiveTask(event.getProcessInstanceId(), taskKey); + } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT)) { + String taskKey = boundaryEvent.getAttachedToRefId(); + taskService.processChildProcessTimeout(event.getProcessInstanceId(), taskKey); } } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 412f630f95..cae5cb9421 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -817,7 +817,8 @@ public class SimpleModelUtils { private static class ChildProcessConvert implements NodeConvert { @Override - public CallActivity convert(BpmSimpleModelNodeVO node) { + public List convertList(BpmSimpleModelNodeVO node) { + List flowElements = new ArrayList<>(2); BpmSimpleModelNodeVO.ChildProcessSetting childProcessSetting = node.getChildProcessSetting(); List inVariables = childProcessSetting.getInVariables() == null ? new ArrayList<>() : new ArrayList<>(childProcessSetting.getInVariables()); @@ -866,9 +867,27 @@ public class SimpleModelUtils { executionListeners.add(flowableListener); callActivity.setExecutionListeners(executionListeners); + // 7. 超时设置 + if (childProcessSetting.getTimeoutSetting() != null) { + BoundaryEvent boundaryEvent = new BoundaryEvent(); + boundaryEvent.setId("Event-" + IdUtil.fastUUID()); + boundaryEvent.setCancelActivity(false); + boundaryEvent.setAttachedToRef(callActivity); + TimerEventDefinition eventDefinition = new TimerEventDefinition(); + if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) { + eventDefinition.setTimeDuration(childProcessSetting.getTimeoutSetting().getTimeExpression()); + } else if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) { + eventDefinition.setTimeDate(childProcessSetting.getTimeoutSetting().getTimeExpression()); + } + boundaryEvent.addEventDefinition(eventDefinition); + addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT.getType()); + flowElements.add(boundaryEvent); + } + // 添加节点类型 addNodeType(node.getType(), callActivity); - return callActivity; + flowElements.add(callActivity); + return flowElements; } @Override diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index 6dce076f87..4c83e30f8a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -284,4 +284,12 @@ public interface BpmTaskService { */ void triggerReceiveTask(String processInstanceId, String taskDefineKey); + /** + * 处理 子流程 审批超时事件 + * + * @param processInstanceId 流程示例编号 + * @param taskDefineKey 任务 Key + */ + void processChildProcessTimeout(String processInstanceId, String taskDefineKey); + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 8f59e6e99d..6bd43749a6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -41,6 +41,7 @@ import org.flowable.engine.ManagementService; import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.history.HistoricActivityInstance; +import org.flowable.engine.runtime.ActivityInstance; import org.flowable.engine.runtime.Execution; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.DelegationState; @@ -1339,6 +1340,17 @@ public class BpmTaskServiceImpl implements BpmTaskService { () -> runtimeService.trigger(execution.getId())); } + @Override + @Transactional(rollbackFor = Exception.class) + public void processChildProcessTimeout(String processInstanceId, String taskDefineKey) { + List activityInstances = runtimeService.createActivityInstanceQuery() + .processInstanceId(processInstanceId) + .activityId(taskDefineKey).list(); + activityInstances.forEach(activityInstance -> FlowableUtils.execute(activityInstance.getTenantId(), () -> { + moveTaskToEnd(activityInstance.getCalledProcessInstanceId(), BpmReasonEnum.TIMEOUT_APPROVE.getReason()); + })); + } + /** * 获得自身的代理对象,解决 AOP 生效问题 * From 48c976cf0a72ff6b1ecc685c6bd13ce2fceb6045 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 25 Feb 2025 12:41:30 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E5=AD=90=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E7=9A=84=E8=B6=85=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/listener/BpmTaskEventListener.java | 1 + .../flowable/core/util/SimpleModelUtils.java | 3 +++ .../task/BpmProcessInstanceServiceImpl.java | 2 +- .../bpm/service/task/BpmTaskService.java | 16 +++++++------- .../bpm/service/task/BpmTaskServiceImpl.java | 21 +++++++++---------- .../listener/BpmCallActivityListener.java | 2 +- 6 files changed, 24 insertions(+), 21 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java index 5ef0b74c3a..b39a0bd623 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java @@ -110,6 +110,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT)) { String taskKey = boundaryEvent.getAttachedToRefId(); taskService.triggerReceiveTask(event.getProcessInstanceId(), taskKey); + // 2.3 子流程超时处理 } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT)) { String taskKey = boundaryEvent.getAttachedToRefId(); taskService.processChildProcessTimeout(event.getProcessInstanceId(), taskKey); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 111ea748b1..898fe55831 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -416,6 +416,7 @@ public class SimpleModelUtils { private BoundaryEvent buildUserTaskTimeoutBoundaryEvent(UserTask userTask, BpmSimpleModelNodeVO.TimeoutHandler timeoutHandler) { // 1.1 定时器边界事件 + // TODO @lesan:一些 BoundaryEvent timeout 的,可以做一些基础的设置么? BoundaryEvent boundaryEvent = new BoundaryEvent(); boundaryEvent.setId("Event-" + IdUtil.fastUUID()); boundaryEvent.setCancelActivity(false); // 设置关联的任务为不会被中断 @@ -723,6 +724,7 @@ public class SimpleModelUtils { // 2. 添加接收任务的 Timer Boundary Event if (node.getDelaySetting() != null) { // 2.1 定时器边界事件 + // TODO @lesan:一些 BoundaryEvent timeout 的,可以做一些基础的设置么? BoundaryEvent boundaryEvent = new BoundaryEvent(); boundaryEvent.setId("Event-" + IdUtil.fastUUID()); boundaryEvent.setCancelActivity(false); @@ -872,6 +874,7 @@ public class SimpleModelUtils { // 7. 超时设置 if (childProcessSetting.getTimeoutSetting() != null) { + // TODO @lesan:一些 BoundaryEvent timeout 的,可以做一些基础的设置么? BoundaryEvent boundaryEvent = new BoundaryEvent(); boundaryEvent.setId("Event-" + IdUtil.fastUUID()); boundaryEvent.setCancelActivity(false); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index b5c9709bd1..ed128f186e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -414,7 +414,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 处理每个任务的 tasks 属性 for (HistoricActivityInstance activity : taskActivities) { HistoricTaskInstance task = taskMap.get(activity.getTaskId()); - // TODO @lesan:这里为啥 continue 哈? @芋艿:子流程的 activity 中 task 是null 下面的方法会报错 + // TODO @lesan:这里为啥 continue 哈? @芋艿:子流程的 activity 中 task 是null 下面的方法会报错;TODO @lesan:写个注释??? if (task == null) { continue; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index d2f9ddec1d..0e493f937e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -276,6 +276,14 @@ public interface BpmTaskService { */ void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer handlerType); + /** + * 处理 ChildProcess 子流程的审批超时事件 + * + * @param processInstanceId 流程示例编号 + * @param taskDefineKey 任务 Key + */ + void processChildProcessTimeout(String processInstanceId, String taskDefineKey); + // TODO @jason:改成 triggerTask。然后,“触发 ReceiveTask,让流程继续执行”,改成一些调用场景 /** * 触发 ReceiveTask,让流程继续执行 @@ -285,12 +293,4 @@ public interface BpmTaskService { */ void triggerReceiveTask(String processInstanceId, String taskDefineKey); - /** - * 处理 子流程 审批超时事件 - * - * @param processInstanceId 流程示例编号 - * @param taskDefineKey 任务 Key - */ - void processChildProcessTimeout(String processInstanceId, String taskDefineKey); - } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 7195fcddad..dc16b0d5f1 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1323,6 +1323,16 @@ public class BpmTaskServiceImpl implements BpmTaskService { })); } + @Override + @Transactional(rollbackFor = Exception.class) + public void processChildProcessTimeout(String processInstanceId, String taskDefineKey) { + List activityInstances = runtimeService.createActivityInstanceQuery() + .processInstanceId(processInstanceId) + .activityId(taskDefineKey).list(); + activityInstances.forEach(activityInstance -> FlowableUtils.execute(activityInstance.getTenantId(), + () -> moveTaskToEnd(activityInstance.getCalledProcessInstanceId(), BpmReasonEnum.TIMEOUT_APPROVE.getReason()))); + } + @Override public void triggerReceiveTask(String processInstanceId, String taskDefineKey) { Execution execution = runtimeService.createExecutionQuery() @@ -1340,17 +1350,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { () -> runtimeService.trigger(execution.getId())); } - @Override - @Transactional(rollbackFor = Exception.class) - public void processChildProcessTimeout(String processInstanceId, String taskDefineKey) { - List activityInstances = runtimeService.createActivityInstanceQuery() - .processInstanceId(processInstanceId) - .activityId(taskDefineKey).list(); - activityInstances.forEach(activityInstance -> FlowableUtils.execute(activityInstance.getTenantId(), () -> { - moveTaskToEnd(activityInstance.getCalledProcessInstanceId(), BpmReasonEnum.TIMEOUT_APPROVE.getReason()); - })); - } - /** * 获得自身的代理对象,解决 AOP 生效问题 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java index 1c2d980380..b454d33335 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java @@ -82,7 +82,7 @@ public class BpmCallActivityListener implements ExecutionListener { try { FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue)); } catch (Exception e) { - log.error("[error][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", + log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", DELEGATE_EXPRESSION, formFieldValue); FlowableUtils.setAuthenticatedUserId(Long.parseLong(parent.getStartUserId())); } From 197c4ad9bf159f6f3f08bf07cbdd14001f1e8b16 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 25 Feb 2025 13:17:27 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91INFRA=EF=BC=9A=E9=94=99=E8=AF=AF=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E3=80=81=E8=AE=BF=E9=97=AE=E6=97=A5=E5=BF=97=EF=BC=8C?= =?UTF-8?q?params=20=E8=BF=87=E9=95=BF=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/service/logger/ApiAccessLogServiceImpl.java | 6 +++--- .../module/infra/service/logger/ApiErrorLogServiceImpl.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java index 9483e8f738..4433fc2a75 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiAccessLogServiceImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.infra.service.logger; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; @@ -35,8 +35,8 @@ public class ApiAccessLogServiceImpl implements ApiAccessLogService { @Override public void createApiAccessLog(ApiAccessLogCreateReqDTO createDTO) { ApiAccessLogDO apiAccessLog = BeanUtils.toBean(createDTO, ApiAccessLogDO.class); - apiAccessLog.setRequestParams(StrUtil.maxLength(apiAccessLog.getRequestParams(), REQUEST_PARAMS_MAX_LENGTH)); - apiAccessLog.setResultMsg(StrUtil.maxLength(apiAccessLog.getResultMsg(), RESULT_MSG_MAX_LENGTH)); + apiAccessLog.setRequestParams(StrUtils.maxLength(apiAccessLog.getRequestParams(), REQUEST_PARAMS_MAX_LENGTH)); + apiAccessLog.setResultMsg(StrUtils.maxLength(apiAccessLog.getResultMsg(), RESULT_MSG_MAX_LENGTH)); if (TenantContextHolder.getTenantId() != null) { apiAccessLogMapper.insert(apiAccessLog); } else { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java index 747b220b5c..1fcbc8dd78 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.infra.service.logger; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.common.util.string.StrUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; @@ -39,7 +39,7 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService { public void createApiErrorLog(ApiErrorLogCreateReqDTO createDTO) { ApiErrorLogDO apiErrorLog = BeanUtils.toBean(createDTO, ApiErrorLogDO.class) .setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus()); - apiErrorLog.setRequestParams(StrUtil.maxLength(apiErrorLog.getRequestParams(), REQUEST_PARAMS_MAX_LENGTH)); + apiErrorLog.setRequestParams(StrUtils.maxLength(apiErrorLog.getRequestParams(), REQUEST_PARAMS_MAX_LENGTH)); if (TenantContextHolder.getTenantId() != null) { apiErrorLogMapper.insert(apiErrorLog); } else {