Commit d0fbb7677cb0d49e06efc10cfadb374ccbd92fc1

Authored by YunaiV
1 parent fda6aff8

【代码评审】BPM:触发器 HTTP 异步

Showing 15 changed files with 44 additions and 31 deletions
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java
1 1 package cn.iocoder.yudao.module.bpm.api.task;
2 2  
3 3 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
4   -
5 4 import jakarta.validation.Valid;
6 5  
7 6 /**
... ... @@ -20,12 +19,13 @@ public interface BpmProcessInstanceApi {
20 19 */
21 20 String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO reqDTO);
22 21  
23   -
  22 + // TODO @jason:新增 BpmProcessTaskApi 接口,这个要不改成 triggerTask,保持通用性(和 flowable 保持一致)
24 23 /**
25 24 * 异步 HTTP 请求触发器回调, 为了唤醒流程继续执行
26 25 *
27 26 * @param processInstanceId 流程实例编号
28   - * @param callbackId 回调编号, 对应 ReceiveTask Id
  27 + * @param callbackId 回调编号, 对应 ReceiveTask Id TODO @jason:改成 taskDefineKey
29 28 */
30 29 void asyncHttpTriggerCallback(String processInstanceId, String callbackId);
  30 +
31 31 }
... ...
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmTriggerTypeEnum.java
... ... @@ -19,7 +19,7 @@ public enum BpmTriggerTypeEnum implements ArrayValuable<Integer> {
19 19 HTTP_REQUEST(1, "发起 HTTP 请求"),
20 20 FORM_UPDATE(2, "更新流程表单数据"),
21 21 FORM_DELETE(3, "删除流程表单数据"),
22   - ASYNC_HTTP_REQUEST(4, "发起异步 HTTP 请求");
  22 + ASYNC_HTTP_REQUEST(4, "发起异步 HTTP 请求"); // TODO @jason:HTTP_REQUEST_ASYNC
23 23  
24 24 /**
25 25 * 触发器执行动作类型
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
... ... @@ -34,4 +34,5 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi {
34 34 public void asyncHttpTriggerCallback(String processInstanceId, String callbackId) {
35 35 bpmTaskService.triggerReceiveTask(processInstanceId, callbackId);
36 36 }
  37 +
37 38 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java
... ... @@ -117,7 +117,8 @@ public class BpmSimpleModelNodeVO {
117 117 @Schema(description = "路由分支组", example = "[]")
118 118 private List<RouterSetting> routerGroups;
119 119  
120   - @Schema(description = "路由分支默认分支 ID", example = "Flow_xxx", hidden = true) // 由后端生成,所以 hidden = true
  120 + @Schema(description = "路由分支默认分支 ID", example = "Flow_xxx", hidden = true) // 由后端生成(不从前端传递),所以 hidden = true
  121 + @JsonIgnore
121 122 private String routerDefaultFlowId; // 仅用于路由分支节点 BpmSimpleModelNodeType.ROUTER_BRANCH_NODE
122 123  
123 124 /**
... ... @@ -125,12 +126,9 @@ public class BpmSimpleModelNodeVO {
125 126 */
126 127 private TriggerSetting triggerSetting;
127 128  
128   - /**
129   - * 附加节点 Id, 该节点不从前端传入。 由程序生成. 由于当个节点无法完成功能。 需要附加节点来完成。
130   - */
  129 + @Schema(description = "附加节点 Id", example = "UserTask_xxx", hidden = true) // 由后端生成(不从前端传递),所以 hidden = true
131 130 @JsonIgnore
132   - private String attachNodeId; // 目前用于异步触发器节点。需要 UserTask 和 ReceiveTask(附加节点) 来完成
133   -
  131 + private String attachNodeId; // 目前用于触发器节点(异步)。需要 UserTask 和 ReceiveTask(附加节点) 来完成
134 132  
135 133 /**
136 134 * 子流程设置
... ... @@ -382,7 +380,6 @@ public class BpmSimpleModelNodeVO {
382 380 @Valid
383 381 private List<HttpRequestParam> body;
384 382  
385   - // TODO @json:可能未来看情况,搞个 HttpResponseParam;得看看有没别的业务需要,抽象统一
386 383 /**
387 384 * 请求返回处理设置,用于修改流程表单值
388 385 * <p>
... ... @@ -392,10 +389,13 @@ public class BpmSimpleModelNodeVO {
392 389 @Schema(description = "请求返回处理设置", example = "[]")
393 390 private List<KeyValue<String, String>> response;
394 391  
  392 + // TODO @jason:改成 callbackTaskDefineKey
395 393 /**
396   - * 异步 Http 请求,需要指定回调 Id,用于回调执行. 由后端指定
  394 + * 异步 Http 请求,需要指定回调 ID,用于回调执行
397 395 */
  396 + @Schema(description = "回调 ID", example = "xxx", hidden = true)
398 397 private String callbackId;
  398 +
399 399 }
400 400  
401 401 @Schema(description = "流程表单触发器设置", example = "{}")
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java
... ... @@ -180,6 +180,7 @@ public class BpmProcessInstanceController {
180 180 return success(processInstanceService.getProcessInstanceBpmnModelView(id));
181 181 }
182 182  
  183 + // TODO @jason:要不去掉这个接口,单体通过 asyncHttpTriggerCallback?
183 184 @PostMapping("/http-trigger/callback")
184 185 @Operation(summary = "异步 HTTP 请求触发器回调")
185 186 @PermitAll // 允许外部调用,不需要登录。 TODO @芋艿 需要加一下验证签名吗?
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmHttpTriggerCallbackReqVO.java
... ... @@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotEmpty;
5 5 import lombok.Data;
6 6  
  7 +// TODO @jason:要不去掉这个接口,单体通过 asyncHttpTriggerCallback?
7 8 @Schema(description = "管理后台 - Bpm 异步 Http 触发器请求回调 Request VO")
8 9 @Data
9 10 public class BpmHttpTriggerCallbackReqVO {
... ... @@ -15,4 +16,5 @@ public class BpmHttpTriggerCallbackReqVO {
15 16 @Schema(description = "回调编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "dca1cdcc-b8fe-11ef-99b5-01ff4722db8b")
16 17 @NotEmpty(message = "回调编号不能为空")
17 18 private String callbackId;
  19 +
18 20 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java
... ... @@ -112,4 +112,5 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
112 112 taskService.triggerReceiveTask(event.getProcessInstanceId(), taskKey);
113 113 }
114 114 }
  115 +
115 116 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java
... ... @@ -171,11 +171,12 @@ public class SimpleModelUtils {
171 171 // 情况二:没有“子节点”,则直接跟 targetNodeId 建立连线。例如说,结束节点、条件分支(分支节点的孩子节点或聚合节点)的最后一个节点
172 172 String finalTargetNodeId = isChildNodeValid ? childNode.getId() : targetNodeId;
173 173  
  174 + // 如果没有附加节点:则直接建立连线
174 175 if (StrUtil.isEmpty(node.getAttachNodeId())) {
175 176 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(node.getId(), finalTargetNodeId);
176 177 process.addFlowElement(sequenceFlow);
177 178 } else {
178   - // 如果有附加节点. 需要先建立和附加节点的连线。再建立附加节点和目标节点的连线
  179 + // 如果有附加节点:需要先建立和附加节点的连线,再建立附加节点和目标节点的连线。例如说,触发器节点(异步)
179 180 List<SequenceFlow> sequenceFlows = buildAttachNodeSequenceFlow(node.getId(), node.getAttachNodeId(), finalTargetNodeId);
180 181 sequenceFlows.forEach(process::addFlowElement);
181 182 }
... ... @@ -189,9 +190,9 @@ public class SimpleModelUtils {
189 190 /**
190 191 * 构建有附加节点的连线
191 192 *
192   - * @param nodeId 当前节点 Id
193   - * @param attachNodeId 附属节点 Id
194   - * @param targetNodeId 目标节点 Id
  193 + * @param nodeId 当前节点 ID
  194 + * @param attachNodeId 附属节点 ID
  195 + * @param targetNodeId 目标节点 ID
195 196 */
196 197 private static List<SequenceFlow> buildAttachNodeSequenceFlow(String nodeId, String attachNodeId, String targetNodeId) {
197 198 SequenceFlow sequenceFlow = buildBpmnSequenceFlow(nodeId, attachNodeId, null, null, null);
... ... @@ -748,8 +749,10 @@ public class SimpleModelUtils {
748 749  
749 750 public static class TriggerNodeConvert implements NodeConvert {
750 751  
  752 + // TODO @芋艿:【异步】在看看
751 753 @Override
752 754 public List<? extends FlowElement> convertList(BpmSimpleModelNodeVO node) {
  755 + Assert.notNull(node.getTriggerSetting(), "触发器节点设置不能为空");
753 756 List<FlowElement> flowElements = new ArrayList<>(2);
754 757 // 触发器使用 ServiceTask 来实现
755 758 ServiceTask serviceTask = new ServiceTask();
... ... @@ -757,23 +760,23 @@ public class SimpleModelUtils {
757 760 serviceTask.setName(node.getName());
758 761 serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
759 762 serviceTask.setImplementation("${" + BpmTriggerTaskDelegate.BEAN_NAME + "}");
760   - Assert.notNull(node.getTriggerSetting(), "触发器节点设置不能为空");
761   -
762 763 addExtensionElement(serviceTask, TRIGGER_TYPE, node.getTriggerSetting().getType());
763 764 flowElements.add(serviceTask);
  765 +
764 766 // 异步 HTTP 请求。需要附加一个 ReceiveTask、发起请求后、等待回调执行
  767 + // TODO @jason:这里能挪到最后处理么?这样,代码的整体性更好;
765 768 if (ASYNC_HTTP_REQUEST.getType().equals(node.getTriggerSetting().getType())) {
  769 + Assert.notNull(node.getTriggerSetting().getHttpRequestSetting(), "触发器 HTTP 请求设置不能为空");
766 770 String attachNodeId = "Activity_" + IdUtil.fastUUID();
767 771 ReceiveTask receiveTask = new ReceiveTask();
768 772 receiveTask.setId(attachNodeId);
769 773 receiveTask.setName("异步 HTTP 请求");
770 774 node.setAttachNodeId(attachNodeId);
771   - // 设置 receiveId
772   - Assert.notNull(node.getTriggerSetting().getHttpRequestSetting(), "触发器 http 请求设置不能为空");
773   - node.getTriggerSetting().getHttpRequestSetting().setCallbackId(attachNodeId);
  775 + node.getTriggerSetting().getHttpRequestSetting().setCallbackId(attachNodeId); // 设置 receiveId
774 776 flowElements.add(receiveTask);
775 777 }
776 778  
  779 + // TODO @jason:是不是挪到 flowElements.add(serviceTask); 之前哈,因为它在处理 serviceTask
777 780 if (node.getTriggerSetting().getHttpRequestSetting() != null) {
778 781 addExtensionElementJson(serviceTask, TRIGGER_PARAM, node.getTriggerSetting().getHttpRequestSetting());
779 782 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java
... ... @@ -276,8 +276,9 @@ public interface BpmTaskService {
276 276 */
277 277 void processTaskTimeout(String processInstanceId, String taskDefineKey, Integer handlerType);
278 278  
  279 + // TODO @jason:改成 triggerTask。然后,“触发 ReceiveTask,让流程继续执行”,改成一些调用场景
279 280 /**
280   - * 触发 ReceiveTask, 让流程继续执行
  281 + * 触发 ReceiveTask,让流程继续执行
281 282 *
282 283 * @param processInstanceId 流程示例编号
283 284 * @param taskDefineKey 任务 Key
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
... ... @@ -1329,7 +1329,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
1329 1329 .activityId(taskDefineKey)
1330 1330 .singleResult();
1331 1331 if (execution == null) {
1332   - log.error("[processDelayTimerTimeout][processInstanceId({}) activityId({}) 没有找到执行活动]",
  1332 + log.error("[triggerReceiveTask][processInstanceId({}) activityId({}) 没有找到执行活动]",
1333 1333 processInstanceId, taskDefineKey);
1334 1334 return;
1335 1335 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormDeleteTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormDeleteTrigger.java
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger;
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.form;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
... ... @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
7 7 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
8 8 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
9 9 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  10 +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
10 11 import com.fasterxml.jackson.core.type.TypeReference;
11 12 import jakarta.annotation.Resource;
12 13 import lombok.extern.slf4j.Slf4j;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmFormUpdateTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/form/BpmFormUpdateTrigger.java
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger;
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.form;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
... ... @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.bpm.enums.definition.BpmTriggerTypeEnum;
7 7 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils;
8 8 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
9 9 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
  10 +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
10 11 import com.fasterxml.jackson.core.type.TypeReference;
11 12 import jakarta.annotation.Resource;
12 13 import lombok.extern.slf4j.Slf4j;
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmAbstractHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmAbstractHttpRequestTrigger.java
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger;
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2 2  
3 3 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
4 4 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.SimpleModelUtils;
  5 +import cn.iocoder.yudao.module.bpm.service.task.trigger.BpmTrigger;
5 6 import jakarta.annotation.Resource;
6 7 import lombok.extern.slf4j.Slf4j;
7 8 import org.flowable.engine.runtime.ProcessInstance;
... ... @@ -39,8 +40,7 @@ public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger {
39 40 HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, headers);
40 41 ResponseEntity<String> responseEntity;
41 42 try {
42   - responseEntity = restTemplate.exchange(url, HttpMethod.POST,
43   - requestEntity, String.class);
  43 + responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
44 44 log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity);
45 45 } catch (RestClientException e) {
46 46 log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage());
... ... @@ -66,4 +66,5 @@ public abstract class BpmAbstractHttpRequestTrigger implements BpmTrigger {
66 66 body.add("processInstanceId", processInstance.getId());
67 67 return body;
68 68 }
  69 +
69 70 }
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmAsyncHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmAsyncHttpRequestTrigger.java
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger;
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2 2  
3 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 4 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO;
... ... @@ -42,7 +42,8 @@ public class BpmAsyncHttpRequestTrigger extends BpmAbstractHttpRequestTrigger {
42 42 MultiValueMap<String, String> headers = buildHttpHeaders(processInstance, setting.getHeader());
43 43 // 2.2 设置请求体
44 44 MultiValueMap<String, String> body = buildHttpBody(processInstance, setting.getBody());
45   - body.add("callbackId", setting.getCallbackId()); // 异步请求 callbackId 需要传给被调用方. 用于回调执行
  45 + // TODO @芋艿:【异步】在看看
  46 + body.add("callbackId", setting.getCallbackId()); // 异步请求 callbackId 需要传给被调用方,用于回调执行
46 47  
47 48 // 3. 发起请求
48 49 sendHttpRequest(setting.getUrl(), headers, body);
... ...
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/BpmSyncHttpRequestTrigger.java renamed to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/trigger/http/BpmSyncHttpRequestTrigger.java
1   -package cn.iocoder.yudao.module.bpm.service.task.trigger;
  1 +package cn.iocoder.yudao.module.bpm.service.task.trigger.http;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.StrUtil;
... ...