You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flowable流程暂停后从JMS监听器重启报错求助

问题分析与解决方案

先拆解你遇到的核心问题:激活流程时的FlowableObjectNotFoundException,以及为什么REST查询不到暂停的流程实例,再逐一给出解决方案和正确的操作方式。

1. 为什么REST查询不到暂停的流程实例?

Flowable的默认流程实例查询接口(包括官方REST API)默认只返回活跃(未挂起)的流程实例。如果要查看挂起的实例,必须明确指定筛选条件:

  • 用REST API时,添加请求参数:?suspended=true(或者suspended=all同时查询活跃和挂起的实例)
  • 用Java API时,需要在查询链中调用.includeSuspended():
List<ProcessInstance> suspendedInstances = runtimeService.createProcessInstanceQuery()
    .includeSuspended()
    .list();

你之前REST查询为空,只是因为没筛选挂起状态,流程实例其实还在数据库里,只是处于暂停状态。

2. 为什么激活时提示找不到流程实例?

可能存在以下几个原因:

(1)硬编码PkgId导致查询匹配失败

你的ValidationDelegate里硬写了pkgMap.setPkgId(1235L);,这意味着所有暂停的流程实例都会关联同一个固定PkgId。如果JMS消息中的PkgId不是1235L,repo.findByPkgId(...)会返回null,后续调用idMap.getProcessInstanceId()要么抛出空指针,要么拿到无效的流程ID,最终触发FlowableObjectNotFoundException。

解决方法:从流程变量中动态获取业务关联的PkgId,比如:

Long pkgId = (Long) delegateExecution.getVariable("pkgId"); // 假设流程中已设置该变量
pkgMap.setPkgId(pkgId);

(2)事务未提交导致数据未持久化

ValidationDelegate中,暂停流程和保存ProcessInstancePkgMap的操作属于流程执行的同一个事务。如果JMS消息在事务提交前就被消费,此时数据库中还没有更新流程实例的挂起状态,也没有写入ProcessInstancePkgMap记录,自然查询不到对应数据。

解决方法:

  • 确保JMS消息的发送逻辑在事务提交之后执行,可以借助Spring的事务同步机制实现;
  • 在JMS监听器中添加重试逻辑,给事务提交留足时间,比如用@Retryable注解实现重试。

(3)RuntimeService获取方式存在风险

你通过CommandContextUtil.getProcessEngineConfiguration().getRuntimeService()获取RuntimeService,在Spring环境下这种方式可能导致事务上下文不一致。更稳妥的做法是直接注入RuntimeService:

@Slf4j 
@Component 
public class ValidationDelegate extends AbstractBaseUtil { 
    protected Expression restEndPoint; 
    @Autowired 
    private ProcessInstancePkgIdMapRepository repo;
    @Autowired
    private RuntimeService runtimeService; // 直接注入Spring管理的实例

    @Override 
    public void executeInternal(DelegateExecution delegateExecution) { 
        runtimeService.suspendProcessInstanceById(delegateExecution.getProcessInstanceId()); 
        ProcessInstancePkgMap pkgMap= new ProcessInstancePkgMap (); 
        Long pkgId = (Long) delegateExecution.getVariable("pkgId");
        pkgMap.setPkgId(pkgId); 
        pkgMap.setProcessInstanceId(delegateExecution.getProcessInstanceId()); 
        ProcessInstancePkgMap map = repo.save(pkgMap); 
        log.info("saved map {}", map); 
    } 
}

3. 暂停流程会导致其终止吗?

绝对不会。Flowable中的suspendProcessInstanceById()只是将流程实例标记为挂起状态,不会终止或删除实例。挂起的实例仍然完整保存在数据库中,只是会暂停执行后续流程节点,直到被主动激活。

真正会终止流程的操作是deleteProcessInstance()或endProcessInstance(),这类操作会彻底结束流程并清理相关运行时数据(历史数据按配置保留)。

4. 暂停/重启挂起工作流的正确方式

(1)正确暂停流程

在流程Delegate中,直接用注入的RuntimeService调用暂停方法即可,确保操作在事务内完成:

// 基础暂停操作
runtimeService.suspendProcessInstanceById(processInstanceId);
// 可选:同时挂起流程中的所有任务,并添加暂停原因
runtimeService.suspendProcessInstanceById(processInstanceId, true, "等待外部验证结果");

(2)正确激活流程

在JMS监听器中,先查询确认流程实例存在且处于挂起状态,再执行激活操作,避免无效调用:

@Component 
public class JMSListener { 
    @Autowired 
    private RuntimeService runtimeService; 
    @Autowired 
    private ProcessInstancePkgIdMapRepository repo; 

    @JmsListener(destination = "test.topic", containerFactory = "jmsListenerContainerFactory") 
    public void receiveMessage(TextMessage message) throws Exception { 
        ObjectMapper objectMapper = new ObjectMapper(); 
        ValidationMessage validationMessage = objectMapper.readValue(message.getText(), ValidationMessage.class); 
        ProcessInstancePkgIdMap idMap = repo.findByPkgId(validationMessage.getPkgId());
        
        if (idMap == null) {
            log.error("No process instance found for PkgId: {}", validationMessage.getPkgId());
            return;
        }

        // 先查询确认流程实例存在且处于挂起状态
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(idMap.getProcessInstanceId())
                .includeSuspended()
                .singleResult();

        if (processInstance != null && processInstance.isSuspended()) {
            runtimeService.activateProcessInstanceById(processInstance.getId());
            log.info("Activated process instance: {}", processInstance.getId());
        } else {
            log.error("Process instance {} not found or not suspended", idMap.getProcessInstanceId());
        }
    } 
}

(3)额外注意事项

  • 给ProcessInstancePkgIdMap表的pkgId字段添加索引,提升查询性能;
  • 在JMS监听器中添加幂等性处理,比如记录已处理的PkgId,避免重复激活同一个流程实例;
  • 完善日志和异常捕获,方便排查问题。

内容的提问来源于stack exchange,提问作者Shenali Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 13:42:48