反序列化问题。

This commit is contained in:
dengqichen 2024-12-18 16:51:29 +08:00
parent a3ea410f5b
commit dd07b181ce
9 changed files with 134 additions and 46 deletions

View File

@ -1,12 +1,11 @@
package com.qqchen.deploy.backend.workflow.config;
import com.qqchen.deploy.backend.workflow.listener.FlowableEventDispatcher;
import com.qqchen.deploy.backend.workflow.listener.event.FlowableEventDispatcher;
import jakarta.annotation.Resource;
import org.flowable.spring.SpringProcessEngineConfiguration;
import org.flowable.spring.boot.EngineConfigurationConfigurer;
import org.springframework.context.annotation.Configuration;
import java.util.Arrays;
import java.util.Collections;
/**

View File

@ -32,7 +32,7 @@ public class WorkflowNodeDefinitionDTO extends BaseDTO {
@Schema(description = "X6图形配置JSON")
private JsonNode graphConfig;
@Schema(description = "排序号")
private Integer orderNum;

View File

@ -1,12 +1,10 @@
package com.qqchen.deploy.backend.workflow.listener;
package com.qqchen.deploy.backend.workflow.listener.event;
import com.qqchen.deploy.backend.workflow.listener.handler.IFlowableEventHandler;
import com.qqchen.deploy.backend.workflow.listener.event.handler.IFlowableEventHandler;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.engine.RuntimeService;
import org.flowable.job.service.impl.persistence.entity.JobEntityImpl;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@ -14,8 +12,6 @@ import jakarta.annotation.Resource;
import java.util.List;
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.ASYNC_CONTINUATION;
@Slf4j
@Component
public class FlowableEventDispatcher implements FlowableEventListener {

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.listener.handler;
package com.qqchen.deploy.backend.workflow.listener.event.handler;
import com.qqchen.deploy.backend.workflow.enums.WorkflowNodeInstanceStatusEnums;
import com.qqchen.deploy.backend.workflow.event.WorkflowNodeInstanceStatusChangeEvent;
@ -13,7 +13,6 @@ import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants.BOUNDARY_EVENT_ERROR_PREFIX;
@ -38,8 +37,6 @@ public class ActivityEventHandler implements IFlowableEventHandler {
if (!(event instanceof FlowableActivityEvent activityEvent)) {
return;
}
// log.info("Processing Flowable event: {}, id: {}, name:{}", eventType, activityEvent.getActivityId(), activityEvent.getActivityName());
List<String> ignoredList = Arrays.asList(BOUNDARY_EVENT_ERROR_PREFIX, END_EVENT_ERROR_PREFIX);
boolean ignored = ignoredList.stream().anyMatch(v -> activityEvent.getActivityId().contains(v));
@ -56,8 +53,7 @@ public class ActivityEventHandler implements IFlowableEventHandler {
.nodeName(StringUtils.isEmpty(activityEvent.getActivityName()) ? activityEvent.getActivityId() : activityEvent.getActivityName())
.nodeType(activityEvent.getActivityType())
.status(status)
.startTime(status == WorkflowNodeInstanceStatusEnums.RUNNING ? LocalDateTime.now() : null)
.endTime(status.isFinalState() ? LocalDateTime.now() : null)
.endTime(LocalDateTime.now())
.build()
);
}
@ -65,8 +61,6 @@ public class ActivityEventHandler implements IFlowableEventHandler {
private WorkflowNodeInstanceStatusEnums convertToNodeStatus(String eventType) {
return switch (eventType) {
case "ACTIVITY_STARTED" -> WorkflowNodeInstanceStatusEnums.RUNNING;
case "ACTIVITY_COMPLETED" -> WorkflowNodeInstanceStatusEnums.COMPLETED;
case "ACTIVITY_CANCELLED" -> WorkflowNodeInstanceStatusEnums.TERMINATED;
case "ACTIVITY_ERROR_RECEIVED" -> WorkflowNodeInstanceStatusEnums.FAILED;
default -> null;

View File

@ -1,9 +1,7 @@
package com.qqchen.deploy.backend.workflow.listener.handler;
package com.qqchen.deploy.backend.workflow.listener.event.handler;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import java.util.List;
/**
* Flowable事件处理器接口
*/

View File

@ -1,10 +1,7 @@
package com.qqchen.deploy.backend.workflow.listener.handler;
package com.qqchen.deploy.backend.workflow.listener.event.handler;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.qqchen.deploy.backend.workflow.enums.WorkflowNodeInstanceStatusEnums;
import com.qqchen.deploy.backend.workflow.event.WorkflowNodeInstanceStatusChangeEvent;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
@ -14,10 +11,6 @@ import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
@Slf4j
@Component
public class JobEventHandler implements IFlowableEventHandler {
@ -36,9 +29,9 @@ public class JobEventHandler implements IFlowableEventHandler {
if (!(event instanceof FlowableEngineEntityEvent entityEvent)) {
return;
}
log.info("Processing job event: {}, jobType: {}", eventType, entityEvent.getType());
//log.info("Processing job event: {}, jobType: {}", eventType, entityEvent.getType());
JobEntityImpl job = (JobEntityImpl) entityEvent.getEntity();
log.info("Processing job event: {}", JSONUtil.toJsonStr(job));
//log.info("Processing job event: {}", JSONUtil.toJsonStr(job));
WorkflowNodeInstanceStatusEnums status = convertToNodeStatus(eventType);
if (status != null) {
// publisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder()

View File

@ -1,4 +1,4 @@
package com.qqchen.deploy.backend.workflow.listener.handler;
package com.qqchen.deploy.backend.workflow.listener.event.handler;
import cn.hutool.core.date.DateUtil;
import com.qqchen.deploy.backend.workflow.enums.WorkflowInstanceStatusEnums;
@ -14,9 +14,6 @@ import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Collections;
import java.util.List;
@Slf4j
@Component
public class ProcessEventHandler implements IFlowableEventHandler {

View File

@ -0,0 +1,62 @@
package com.qqchen.deploy.backend.workflow.listener.execution;
import com.qqchen.deploy.backend.workflow.enums.WorkflowNodeInstanceStatusEnums;
import com.qqchen.deploy.backend.workflow.event.WorkflowNodeInstanceStatusChangeEvent;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.time.LocalDateTime;
@Slf4j
@Component("globalNodeExecutionListener")
public class GlobalExecutionListener implements ExecutionListener {
@Resource
private ApplicationEventPublisher eventPublisher;
@Override
public void notify(DelegateExecution execution) {
// 获取当前节点信息
FlowElement flowElement = execution.getCurrentFlowElement();
String eventName = execution.getEventName();
String processInstanceId = execution.getProcessInstanceId();
String executionId = execution.getId();
String nodeId = execution.getCurrentActivityId();
String nodeName = flowElement.getName();
String nodeType = flowElement.getClass().getSimpleName();
log.debug("Node execution event: {}, processInstanceId: {}, nodeId: {}, nodeType: {}, nodeName:{}", eventName, processInstanceId, nodeId, nodeType, nodeName);
LocalDateTime now = LocalDateTime.now();
WorkflowNodeInstanceStatusEnums status = null;
LocalDateTime startTime = null;
LocalDateTime endTime = null;
switch (eventName) {
case ExecutionListener.EVENTNAME_START:
status = WorkflowNodeInstanceStatusEnums.RUNNING;
startTime = now;
break;
case ExecutionListener.EVENTNAME_END:
status = WorkflowNodeInstanceStatusEnums.COMPLETED;
endTime = now;
break;
default:
log.warn("Unexpected event type: {}", eventName);
return;
}
eventPublisher.publishEvent(WorkflowNodeInstanceStatusChangeEvent.builder()
.processInstanceId(processInstanceId)
.executionId(executionId)
.nodeId(nodeId)
.nodeName(nodeName)
.nodeType(nodeType)
.status(status)
.startTime(startTime)
.endTime(endTime)
.build());
}
}

View File

@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -118,26 +119,37 @@ public class BpmnConverter {
* @param process 当前流程
*/
private void configureFlowElement(FlowElement element, WorkflowDefinitionNode node, Process process) {
// 为所有节点添加执行监听器
Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
List<ExtensionElement> executionListeners = new ArrayList<>();
// 开始事件监听器
ExtensionElement startListener = createExecutionListener("start", "${globalNodeExecutionListener}");
executionListeners.add(startListener);
// 结束事件监听器
ExtensionElement endListener = createExecutionListener("end", "${globalNodeExecutionListener}");
executionListeners.add(endListener);
extensionElements.put("executionListener", executionListeners);
// 根据节点类型进行特定配置
if (element instanceof ServiceTask) {
ServiceTask serviceTask = (ServiceTask) element;
// 设置委托表达式
String delegate = (String) node.getConfig().get("delegate");
// serviceTask.setImplementationType("class");
// serviceTask.setImplementation("com.qqchen.deploy.backend.workflow.delegate.ShellTaskDelegate");
serviceTask.setImplementationType("delegateExpression");
serviceTask.setImplementation(delegate);
// serviceTask.setAsynchronous(false); // 设置为异步执行
// 设置失败时不重试
ExtensionElement failedJobRetryTimeCycle = new ExtensionElement();
failedJobRetryTimeCycle.setName("failedJobRetryTimeCycle");
failedJobRetryTimeCycle.setNamespace("http://flowable.org/bpmn");
failedJobRetryTimeCycle.setNamespacePrefix("flowable");
failedJobRetryTimeCycle.setElementText("R0/PT1H"); // 设置为0次重试
// 配置重试策略
ExtensionElement retryConfig = new ExtensionElement();
retryConfig.setName("failedJobRetryTimeCycle");
retryConfig.setNamespace("http://flowable.org/bpmn");
retryConfig.setNamespacePrefix("flowable");
retryConfig.setElementText("R0/PT1H"); // 设置为0次重试
Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
List<ExtensionElement> retryElements = new ArrayList<>();
retryElements.add(failedJobRetryTimeCycle);
retryElements.add(retryConfig);
extensionElements.put("failedJobRetryTimeCycle", retryElements);
// 添加字段注入
@ -150,16 +162,53 @@ public class BpmnConverter {
fieldExtensions.add(fieldExtension);
}
});
// 设置到服务任务
serviceTask.setFieldExtensions(fieldExtensions);
serviceTask.setExtensionElements(extensionElements);
// 添加错误边界事件
addErrorBoundaryEventHandler(process, serviceTask);
} else if (element instanceof StartEvent || element instanceof EndEvent) {
// 为开始节点和结束节点设置监听器
element.setExtensionElements(extensionElements);
}
}
/**
* 为服务任务添加错误边界事件和错误结束事件
* 创建执行监听器扩展元素
*
* @param event 事件类型start/end
* @param delegateExpression 委托表达式
* @return 配置好的监听器扩展元素
*/
private ExtensionElement createExecutionListener(String event, String delegateExpression) {
ExtensionElement listener = new ExtensionElement();
listener.setName("executionListener");
listener.setNamespace("http://flowable.org/bpmn");
listener.setNamespacePrefix("flowable");
// 设置事件属性
ExtensionAttribute eventAttr = new ExtensionAttribute();
eventAttr.setName("event");
eventAttr.setValue(event);
// 设置委托表达式属性
ExtensionAttribute delegateAttr = new ExtensionAttribute();
delegateAttr.setName("delegateExpression");
delegateAttr.setValue(delegateExpression);
// 添加属性到监听器
Map<String, List<ExtensionAttribute>> attributes = new HashMap<>();
attributes.put("event", Collections.singletonList(eventAttr));
attributes.put("delegateExpression", Collections.singletonList(delegateAttr));
listener.setAttributes(attributes);
return listener;
}
/**
* 为服务任务添加错误边界事件和错误结<EFBFBD><EFBFBD><EFBFBD>事件
* 当服务任务执行失败时会触发错误边界事件并流转到错误结束事件
*
* @param process BPMN流程定义