feat(workflow): 从hwbm的新版本plus框架中直接复制,未经过测试!新增流程实例业务扩展对象和启动流程并推进功能

- 新增 FlowInstanceBizExt 类作为流程实例业务扩展对象
- 在 RemoteStartProcess 中添加 bizExt 字段用于业务扩展信息
- 在 StartProcessBo 中添加 bizExt 字段用于业务扩展信息
- 新增 startCompleteTask 方法实现启动流程并自动推进到下一节点
- 实现 getCurrentTaskIdByInstanceId 方法根据流程实例ID获取当前活跃任务
- 通过独立事务机制避免数据库死锁问题
- 添加完整的注释文档说明新功能的使用场景和核心机制
master
zangch@mesnac.com 2 days ago
parent e75762694e
commit 871696d50a

@ -89,7 +89,7 @@ public interface RemoteWorkflowService {
*
*
* completeTask.getVariables().put("ignore", true);
*
*
* @param taskId ID
* @param message
*/
@ -98,7 +98,7 @@ public interface RemoteWorkflowService {
/**
* IDID
* ID
*
*
* @param businessId ID
* @return IDnull
*/
@ -106,10 +106,30 @@ public interface RemoteWorkflowService {
/**
* IDID
*
*
* @param instanceId ID
* @return IDnull
*/
Long getCurrentTaskIdByInstanceId(Long instanceId);
/**
* hwbmplus
*
* <p>
* startWorkFlow() completeTask()
* 使
* </p>
* <p>
*
* <ul>
* <li></li>
* <li> flow_instance flow_task </li>
* </ul>
* </p>
*
* @param startProcess flowCode, businessId, variables
* @return true=, false=
*/
boolean startCompleteTask(RemoteStartProcess startProcess);
}

@ -1,6 +1,7 @@
package org.dromara.workflow.api.domain;
import cn.hutool.core.util.ObjectUtil;
import lombok.Data;
import java.io.Serial;
@ -35,6 +36,13 @@ public class RemoteStartProcess implements Serializable {
*/
private Map<String, Object> variables;
/**
* hwbmplus
*
*
*/
private Object bizExt;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
@ -42,4 +50,13 @@ public class RemoteStartProcess implements Serializable {
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
//从hwbm的新版本plus框架中直接复制未经过测试
public Object getBizExt() {
if (ObjectUtil.isNull(bizExt)) {
bizExt = new Object();
}
return bizExt;
}
}

@ -0,0 +1,60 @@
package org.dromara.workflow.domain;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
/**
* hwbmplus
* flow_instance_biz_ext
*
* @author may
* @date 2025-08-05
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("flow_instance_biz_ext")
public class FlowInstanceBizExt extends TenantEntity {
@Serial
private static final long serialVersionUID = 1L;
/**
*
*/
@TableId(value = "id")
private Long id;
/**
* ID
*/
private Long instanceId;
/**
* ID
*/
private String businessId;
/**
*
*/
private String businessCode;
/**
*
*/
private String businessTitle;
/**
* 0 1
*/
@TableLogic
private String delFlag;
}

@ -1,6 +1,7 @@
package org.dromara.workflow.domain.bo;
import cn.hutool.core.util.ObjectUtil;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.dromara.common.core.validate.AddGroup;
@ -39,6 +40,13 @@ public class StartProcessBo implements Serializable {
*/
private Map<String, Object> variables;
/**
* hwbmplus
*
*
*/
private Object bizExt;
public Map<String, Object> getVariables() {
if (variables == null) {
return new HashMap<>(16);
@ -46,4 +54,13 @@ public class StartProcessBo implements Serializable {
variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue()));
return variables;
}
//从hwbm的新版本plus框架中直接复制未经过测试
public Object getBizExt() {
if (ObjectUtil.isNull(bizExt)) {
bizExt = new Object();
}
return bizExt;
}
}

@ -83,4 +83,10 @@ public class RemoteWorkflowServiceImpl implements RemoteWorkflowService {
return workflowService.getCurrentTaskIdByInstanceId(instanceId);
}
//从hwbm的新版本plus框架中直接复制未经过测试
@Override
public boolean startCompleteTask(RemoteStartProcess startProcess) {
return workflowService.startCompleteTask(startProcess);
}
}

@ -95,7 +95,7 @@ public interface WorkflowService {
/**
* IDID
* ID
*
*
* @param businessId ID
* @return IDnull
*/
@ -103,10 +103,23 @@ public interface WorkflowService {
/**
* IDID
*
*
* @param instanceId ID
* @return IDnull
*/
Long getCurrentTaskIdByInstanceId(Long instanceId);
/**
* hwbmplus
*
* <p>
* startWorkFlow() completeTask()
* 使
* </p>
*
* @param startProcess flowCode, businessId, variables
* @return true=, false=
*/
boolean startCompleteTask(RemoteStartProcess startProcess);
}

@ -4,12 +4,15 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.warm.flow.orm.entity.FlowInstance;
import org.dromara.workflow.api.domain.RemoteCompleteTask;
import org.dromara.workflow.api.domain.RemoteStartProcess;
import org.dromara.workflow.api.domain.RemoteStartProcessReturn;
import org.dromara.workflow.common.ConditionalOnEnable;
import org.dromara.workflow.common.enums.MessageTypeEnum;
import org.dromara.workflow.domain.FlowInstanceBizExt;
import org.dromara.workflow.domain.bo.CompleteTaskBo;
import org.dromara.workflow.domain.bo.StartProcessBo;
import org.dromara.workflow.service.IFlwDefinitionService;
@ -17,7 +20,10 @@ import org.dromara.workflow.service.IFlwInstanceService;
import org.dromara.workflow.service.IFlwTaskService;
import org.dromara.workflow.service.WorkflowService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -154,7 +160,7 @@ public class WorkflowServiceImpl implements WorkflowService {
/**
* IDID
* ID
*
*
* @param businessId ID
* @return IDnull
*/
@ -165,14 +171,14 @@ public class WorkflowServiceImpl implements WorkflowService {
if (instanceId == null) {
return null;
}
// 通过流程实例ID获取当前活跃任务ID
return getCurrentTaskIdByInstanceId(instanceId);
}
/**
* IDID
*
*
* @param instanceId ID
* @return IDnull
*/
@ -181,16 +187,16 @@ public class WorkflowServiceImpl implements WorkflowService {
if (instanceId == null) {
return null;
}
try {
// 获取该流程实例下的所有活跃任务
List<org.dromara.warm.flow.orm.entity.FlowTask> activeTasks = flwTaskService.selectByInstId(instanceId);
// 过滤出当前活跃的任务del_flag=0
Optional<org.dromara.warm.flow.orm.entity.FlowTask> activeTask = activeTasks.stream()
.filter(task -> "0".equals(task.getDelFlag()))
.findFirst();
return activeTask.map(org.dromara.warm.flow.orm.entity.FlowTask::getId).orElse(null);
} catch (Exception e) {
log.error("获取当前活跃任务失败instanceId: {}", instanceId, e);
@ -198,4 +204,129 @@ public class WorkflowServiceImpl implements WorkflowService {
}
}
/**
*
* <p>
* startWorkFlow() completeTask()
* 使
* </p>
* <p>
*
* <ul>
* <li>1. 1 flow_instance flow_task</li>
* <li>2. 1</li>
* <li>3. 2</li>
* </ul>
* </p>
*
* @param startProcess
* @return true=, false=
*/
// @Override
// public boolean startCompleteTask(RemoteStartProcess startProcess) {
// try {
// // 阶段1启动流程独立事务
// // startWorkFlow() 方法已有 @Transactional 注解,会在独立事务中执行
// RemoteStartProcessReturn startResult = flwTaskService.startWorkFlow(
// BeanUtil.toBean(startProcess, StartProcessBo.class)
// );
//
// if (startResult == null || startResult.getTaskId() == null) {
// log.error("启动工作流失败flowCode: {}, businessId: {}",
// startProcess.getFlowCode(), startProcess.getBusinessId());
// return false;
// }
//
// Long taskId = startResult.getTaskId();
//
// // 阶段1事务已提交数据库锁已释放
//
// // 阶段2推进流程新独立事务
// // 使用 REQUIRES_NEW 确保在新事务中执行避免与阶段1的事务冲突
// return completeTaskInNewTransaction(taskId, startProcess);
//
// } catch (Exception e) {
// log.error("startCompleteTask 执行异常flowCode: {}, businessId: {}, error: {}",
// startProcess.getFlowCode(), startProcess.getBusinessId(), e.getMessage(), e);
// return false;
// }
// }
/**
*
* <p>
* 使 REQUIRES_NEW
* startWorkFlow()
* </p>
*
* @param taskId ID
* @param startProcess variables
* @return true=, false=
*/
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
protected boolean completeTaskInNewTransaction(Long taskId, RemoteStartProcess startProcess) {
try {
RemoteCompleteTask completeTask = new RemoteCompleteTask();
completeTask.setTaskId(taskId);
// 传递 variables如果有
// variables 可以包含流程分支条件、message、messageType、notice 等参数
if (startProcess.getVariables() != null && !startProcess.getVariables().isEmpty()) {
completeTask.setVariables(startProcess.getVariables());
}
// 调用 completeTask在新事务中
boolean result = flwTaskService.completeTask(BeanUtil.toBean(completeTask, CompleteTaskBo.class));
if (result) {
log.info("工作流启动并推进成功flowCode: {}, businessId: {}, taskId: {}",
startProcess.getFlowCode(), startProcess.getBusinessId(), taskId);
} else {
log.warn("工作流推进失败flowCode: {}, businessId: {}, taskId: {}",
startProcess.getFlowCode(), startProcess.getBusinessId(), taskId);
}
return result;
} catch (Exception e) {
log.error("completeTaskInNewTransaction 执行异常taskId: {}, businessId: {}, error: {}",
taskId, startProcess.getBusinessId(), e.getMessage(), e);
throw e; // 重新抛出异常,触发事务回滚
}
}
/**
*
* hwbmplus
*
* @param startProcess
*/
@Override
public boolean startCompleteTask(RemoteStartProcess startProcess) {
try {
StartProcessBo processBo = new StartProcessBo();
processBo.setBusinessId(startProcess.getBusinessId());
processBo.setFlowCode(startProcess.getFlowCode());
processBo.setVariables(startProcess.getVariables());
// processBo.setHandler(startProcess.getHandler());
processBo.setBizExt(BeanUtil.toBean(startProcess.getBizExt(), FlowInstanceBizExt.class));
RemoteStartProcessReturn result = flwTaskService.startWorkFlow(processBo);
CompleteTaskBo taskBo = new CompleteTaskBo();
taskBo.setTaskId(result.getTaskId());
taskBo.setMessageType(Collections.singletonList(MessageTypeEnum.SYSTEM_MESSAGE.getCode()));
taskBo.setVariables(startProcess.getVariables());
// taskBo.setHandler(startProcess.getHandler());
boolean flag = flwTaskService.completeTask(taskBo);
if (!flag) {
throw new ServiceException("流程发起异常");
}
return true;
} catch (Exception e) {
throw new ServiceException(e.getMessage());
}
}
}

Loading…
Cancel
Save