反序列化问题。

This commit is contained in:
dengqichen 2024-12-16 17:34:35 +08:00
parent 88b5588531
commit 92471a8ce2
6 changed files with 102 additions and 100 deletions

View File

@ -0,0 +1,11 @@
package com.qqchen.deploy.backend.workflow.constants;
public interface WorkFlowConstants {
public static final String WORKFLOW_EXEC_ERROR = "WORKFLOW_EXEC_ERROR";
public static final String BOUNDARY_EVENT_ERROR_PREFIX = "BOUNDARY_EVENT_ERROR_";
public static final String END_EVENT_ERROR_PREFIX = "END_EVENT_ERROR_";
public static final String SEQUENCE_FLOW_ERROR_PREFIX = "SEQUENCE_FLOW_ERROR_";
}

View File

@ -1,11 +1,13 @@
package com.qqchen.deploy.backend.workflow.delegate; package com.qqchen.deploy.backend.workflow.delegate;
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
import com.qqchen.deploy.backend.workflow.event.ShellLogEvent; import com.qqchen.deploy.backend.workflow.event.ShellLogEvent;
import com.qqchen.deploy.backend.workflow.enums.NodeLogTypeEnums; import com.qqchen.deploy.backend.workflow.enums.NodeLogTypeEnums;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableException; import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.RuntimeService; import org.flowable.engine.RuntimeService;
import org.flowable.engine.ManagementService; import org.flowable.engine.ManagementService;
import org.flowable.engine.delegate.BpmnError;
import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate; import org.flowable.engine.delegate.JavaDelegate;
import org.flowable.common.engine.api.delegate.Expression; import org.flowable.common.engine.api.delegate.Expression;
@ -78,8 +80,7 @@ public class ShellTaskDelegate implements JavaDelegate {
if (scriptValue == null) { if (scriptValue == null) {
log.error("脚本内容为空,执行失败"); log.error("脚本内容为空,执行失败");
handleFailure(execution, "Script is required but not provided"); throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, "Script is required but not provided");
return;
} }
try { try {
@ -169,8 +170,7 @@ public class ShellTaskDelegate implements JavaDelegate {
if (exitCode != 0) { if (exitCode != 0) {
log.error("Shell脚本执行失败退出码: {}", exitCode); log.error("Shell脚本执行失败退出码: {}", exitCode);
log.error("错误输出: {}", finalError); log.error("错误输出: {}", finalError);
handleFailure(execution, "Shell脚本执行失败退出码: " + exitCode); throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, "Shell脚本执行失败退出码: " + exitCode);
return;
} }
log.info("Shell脚本执行成功"); log.info("Shell脚本执行成功");
@ -178,14 +178,7 @@ public class ShellTaskDelegate implements JavaDelegate {
} catch (Exception e) { } catch (Exception e) {
log.error("Shell脚本执行失败", e); log.error("Shell脚本执行失败", e);
// Job job = managementService.createJobQuery() throw new BpmnError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, "Shell脚本执行失败");
// .processInstanceId(execution.getProcessInstanceId())
// .singleResult();
// if (job != null) {
// // 设置重试次数为 0这样就不会进入死信队列
// managementService.setJobRetries(job.getId(), 0);
// }
throw new FlowableException("脚本执行失败。");
} }
} }
@ -217,25 +210,4 @@ public class ShellTaskDelegate implements JavaDelegate {
} }
private void handleFailure(DelegateExecution execution, String errorMessage) {
String processInstanceId = execution.getProcessInstanceId();
// 获取当前 Job
Job job = managementService.createJobQuery()
.processInstanceId(execution.getProcessInstanceId())
.singleResult();
if (job != null) {
// 设置重试次数为 0这样就不会进入死信队列
managementService.setJobRetries(job.getId(), 0);
}
throw new FlowableException(errorMessage);
// try {
// 直接终止流程实例
// runtimeService.deleteProcessInstance(processInstanceId, errorMessage);
// } catch (Exception e) {
// log.error("处理Shell任务失败时出现错误流程实例: {}", processInstanceId, e);
// }
}
} }

View File

@ -26,7 +26,7 @@ public class ActivityEventHandler implements IFlowableEventHandler {
@Override @Override
public void handle(FlowableEvent event) { public void handle(FlowableEvent event) {
String eventType = event.getType().name(); String eventType = event.getType().name();
log.info("Processing activity event: {}", eventType); // log.info("Processing activity event: {}", eventType);
if (!(event instanceof FlowableActivityEvent activityEvent)) { if (!(event instanceof FlowableActivityEvent activityEvent)) {
return; return;
@ -35,17 +35,17 @@ public class ActivityEventHandler implements IFlowableEventHandler {
WorkflowNodeInstanceStatusEnums status = convertToNodeStatus(eventType); WorkflowNodeInstanceStatusEnums status = convertToNodeStatus(eventType);
if (status != null) { if (status != null) {
publisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder() // publisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder()
.processInstanceId(activityEvent.getProcessInstanceId()) // .processInstanceId(activityEvent.getProcessInstanceId())
.executionId(activityEvent.getExecutionId()) // .executionId(activityEvent.getExecutionId())
.nodeId(activityEvent.getActivityId()) // .nodeId(activityEvent.getActivityId())
.nodeName(activityEvent.getActivityName()) // .nodeName(activityEvent.getActivityName())
.nodeType(activityEvent.getActivityType()) // .nodeType(activityEvent.getActivityType())
.status(status) // .status(status)
.startTime(status == WorkflowNodeInstanceStatusEnums.RUNNING ? LocalDateTime.now() : null) // .startTime(status == WorkflowNodeInstanceStatusEnums.RUNNING ? LocalDateTime.now() : null)
.endTime(status.isFinalState() ? LocalDateTime.now() : null) // .endTime(status.isFinalState() ? LocalDateTime.now() : null)
.build() // .build()
); // );
} }
} }

View File

@ -28,29 +28,29 @@ public class JobEventHandler implements IFlowableEventHandler {
@Override @Override
public void handle(FlowableEvent event) { public void handle(FlowableEvent event) {
String eventType = event.getType().name(); String eventType = event.getType().name();
log.info("Processing job event: {}", eventType); // log.info("Processing job event: {}", eventType);
if (!(event instanceof FlowableEngineEntityEvent entityEvent)) { if (!(event instanceof FlowableEngineEntityEvent entityEvent)) {
return; return;
} }
log.info("Processing job event: {}, jobType: {}", eventType, entityEvent.getType()); // log.info("Processing job event: {}, jobType: {}", eventType, entityEvent.getType());
JobEntityImpl job = (JobEntityImpl) entityEvent.getEntity(); JobEntityImpl job = (JobEntityImpl) entityEvent.getEntity();
WorkflowNodeInstanceStatusEnums status = convertToNodeStatus(eventType); WorkflowNodeInstanceStatusEnums status = convertToNodeStatus(eventType);
if (status != null) { if (status != null) {
publisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder() // publisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder()
.processInstanceId(job.getProcessInstanceId()) // .processInstanceId(job.getProcessInstanceId())
.executionId(job.getExecutionId()) // .executionId(job.getExecutionId())
.nodeId(job.getElementId()) // .nodeId(job.getElementId())
.nodeName(job.getElementName()) // .nodeName(job.getElementName())
.nodeType(job.getJobHandlerType()) // .nodeType(job.getJobHandlerType())
.status(status) // .status(status)
.startTime(job.getCreateTime() != null ? DateUtil.toLocalDateTime(job.getCreateTime()) : null) // .startTime(job.getCreateTime() != null ? DateUtil.toLocalDateTime(job.getCreateTime()) : null)
.endTime(status.isFinalState() ? LocalDateTime.now() : null) // .endTime(status.isFinalState() ? LocalDateTime.now() : null)
.build() // .build()
); // );
} }
} }

View File

@ -33,24 +33,24 @@ public class ProcessEventHandler implements IFlowableEventHandler {
@Override @Override
public void handle(FlowableEvent event) { public void handle(FlowableEvent event) {
String eventType = event.getType().name(); String eventType = event.getType().name();
log.info("Processing event: {}", eventType); // log.info("Processing event: {}", eventType);
FlowableProcessEngineEvent processEvent = (FlowableProcessEngineEvent) event; FlowableProcessEngineEvent processEvent = (FlowableProcessEngineEvent) event;
WorkflowInstanceStatusEnums status = convertToWorkflowStatus(eventType); WorkflowInstanceStatusEnums status = convertToWorkflowStatus(eventType);
if (status != null) { if (status != null) {
HistoricProcessInstance historicProcessInstance = processEngine.getHistoryService() // HistoricProcessInstance historicProcessInstance = processEngine.getHistoryService()
.createHistoricProcessInstanceQuery() // .createHistoricProcessInstanceQuery()
.processInstanceId(processEvent.getProcessInstanceId()) // .processInstanceId(processEvent.getProcessInstanceId())
.singleResult(); // .singleResult();
//
publisher.publishEvent(WorkflowInstanceStatusChangeEvent.builder() // publisher.publishEvent(WorkflowInstanceStatusChangeEvent.builder()
.processInstanceId(processEvent.getProcessInstanceId()) // .processInstanceId(processEvent.getProcessInstanceId())
.status(status) // .status(status)
.endTime(historicProcessInstance != null && historicProcessInstance.getEndTime() != null ? // .endTime(historicProcessInstance != null && historicProcessInstance.getEndTime() != null ?
DateUtil.toLocalDateTime(historicProcessInstance.getEndTime()) : null) // DateUtil.toLocalDateTime(historicProcessInstance.getEndTime()) : null)
.build() // .build()
); // );
} }
} }

View File

@ -1,5 +1,6 @@
package com.qqchen.deploy.backend.workflow.util; package com.qqchen.deploy.backend.workflow.util;
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
import com.qqchen.deploy.backend.workflow.dto.graph.*; import com.qqchen.deploy.backend.workflow.dto.graph.*;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums; import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -38,6 +39,8 @@ public class BpmnConverter {
// 创建BPMN模型 // 创建BPMN模型
BpmnModel bpmnModel = new BpmnModel(); BpmnModel bpmnModel = new BpmnModel();
bpmnModel.setTargetNamespace("http://www.flowable.org/test");
Process process = new Process(); Process process = new Process();
// 确保processKey符合NCName规则 // 确保processKey符合NCName规则
String validProcessKey = processKey.replaceAll("[^a-zA-Z0-9-_.]", "_"); String validProcessKey = processKey.replaceAll("[^a-zA-Z0-9-_.]", "_");
@ -67,7 +70,7 @@ public class BpmnConverter {
element.setName(node.getName()); element.setName(node.getName());
// 设置节点特定属性 // 设置节点特定属性
configureFlowElement(element, node); configureFlowElement(element, node, process);
process.addFlowElement(element); process.addFlowElement(element);
} }
@ -109,8 +112,9 @@ public class BpmnConverter {
* 配置流程节点的特定属性 * 配置流程节点的特定属性
* @param element 流程节点元素 * @param element 流程节点元素
* @param node 工作流节点定义 * @param node 工作流节点定义
* @param process 当前流程
*/ */
private void configureFlowElement(FlowElement element, WorkflowDefinitionNode node) { private void configureFlowElement(FlowElement element, WorkflowDefinitionNode node, Process process) {
if (element instanceof ServiceTask) { if (element instanceof ServiceTask) {
ServiceTask serviceTask = (ServiceTask) element; ServiceTask serviceTask = (ServiceTask) element;
// 设置委托表达式 // 设置委托表达式
@ -126,42 +130,57 @@ public class BpmnConverter {
failedJobRetryTimeCycle.setNamespacePrefix("flowable"); failedJobRetryTimeCycle.setNamespacePrefix("flowable");
failedJobRetryTimeCycle.setElementText("R0/PT1H"); // 设置为0次重试 failedJobRetryTimeCycle.setElementText("R0/PT1H"); // 设置为0次重试
// 添加错误处理配置
ExtensionElement errorHandling = new ExtensionElement();
errorHandling.setName("failOnError");
errorHandling.setNamespace("http://flowable.org/bpmn");
errorHandling.setNamespacePrefix("flowable");
errorHandling.setElementText("true");
Map<String, List<ExtensionElement>> extensionElements = new HashMap<>(); Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
List<ExtensionElement> retryElements = new ArrayList<>(); List<ExtensionElement> retryElements = new ArrayList<>();
retryElements.add(failedJobRetryTimeCycle); retryElements.add(failedJobRetryTimeCycle);
extensionElements.put("failedJobRetryTimeCycle", retryElements); extensionElements.put("failedJobRetryTimeCycle", retryElements);
List<ExtensionElement> errorElements = new ArrayList<>(); // 添加字段注入
errorElements.add(errorHandling); List<FieldExtension> fieldExtensions = new ArrayList<>();
extensionElements.put("failOnError", errorElements); node.getConfig().forEach((key, value) -> {
if (value != null && !"delegate".equals(key)) {
FieldExtension fieldExtension = new FieldExtension();
fieldExtension.setFieldName(key);
fieldExtension.setStringValue(String.valueOf(value));
fieldExtensions.add(fieldExtension);
}
});
serviceTask.setFieldExtensions(fieldExtensions);
serviceTask.setExtensionElements(extensionElements); serviceTask.setExtensionElements(extensionElements);
}
// 后续可以添加其他类型的节点配置 // 添加错误边界事件
// else if (element instanceof UserTask) { ... } BoundaryEvent boundaryEvent = new BoundaryEvent();
} boundaryEvent.setId("error_boundary_" + serviceTask.getId());
boundaryEvent.setName("错误边界事件");
boundaryEvent.setAttachedToRef(serviceTask);
boundaryEvent.setAttachedToRefId(serviceTask.getId());
boundaryEvent.setCancelActivity(true); // 确保取消原有活动
// 配置错误事件定义
ErrorEventDefinition errorEventDefinition = new ErrorEventDefinition();
errorEventDefinition.setErrorCode(WorkFlowConstants.WORKFLOW_EXEC_ERROR);
boundaryEvent.addEventDefinition(errorEventDefinition);
// 添加错误结束事件
EndEvent errorEndEvent = new EndEvent();
errorEndEvent.setId("error_end_" + serviceTask.getId());
errorEndEvent.setName("错误结束事件");
/** // 添加终止定义
* 添加扩展属性 TerminateEventDefinition terminateEventDefinition = new TerminateEventDefinition();
*/ errorEndEvent.addEventDefinition(terminateEventDefinition);
private void addExtensionElement(Map<String, List<ExtensionElement>> extensionElements, String name, String value) {
if (value != null && !value.trim().isEmpty()) {
ExtensionElement extensionElement = new ExtensionElement();
extensionElement.setName(name);
extensionElement.setNamespace("http://flowable.org/bpmn");
extensionElement.setNamespacePrefix("flowable");
// 直接设置文本值让Flowable自己处理XML转义 // 添加从边界事件到结束事件的连线
extensionElement.setElementText(value); SequenceFlow errorFlow = new SequenceFlow();
errorFlow.setId("error_flow_" + serviceTask.getId());
errorFlow.setName("错误处理流程");
errorFlow.setSourceRef(boundaryEvent.getId());
errorFlow.setTargetRef(errorEndEvent.getId());
extensionElements.computeIfAbsent(name, k -> new ArrayList<>()).add(extensionElement); // 将错误处理相关的元素添加到流程中
process.addFlowElement(boundaryEvent);
process.addFlowElement(errorEndEvent);
process.addFlowElement(errorFlow);
} }
} }
} }