Activiti7流程结束监听事件中,抛出的异常无法被spring全局异常捕捉

ProcessRuntimeEventListener

activiti7中,提供了ProcessRuntimeEventListener监听器,用于监听流程实例的结束事件

/**
 * 流程完成监听器
 */
@Slf4j
@Component
public class ProcessCompleteListener implements ProcessRuntimeEventListener<ProcessCompletedEvent> {

    @Override
    public void onEvent(ProcessCompletedEvent event) {
        // ...处理自己的业务逻辑
	
		// 这里写一段抛出异常的测试代码
		int a = 1 / 0;
    }
}

上述代码中,由于1/0会抛出运行时异常,理论上来说应该被我们的全局异常所捕获

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 通用未知异常
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.OK)
    public ResultEntity<?> error(Exception e) {
        return ResultEntity.fail(ResultEnum.SERVER_ERROR, "系统错误,请联系管理员!");
    }

}

实际情况是无法捕获

解决思路

既然异常没有被一层一层的抛出去直到被全局异常捕获,那说明调用ProcessCompleteListener.onEvent()的某个地方使用try catch将异常捕获了该异常并没有继续向上抛出,随着这个思路,我们将断点打在1/0这行代码上面

在这里插入图片描述
然后重新运行代码,让代码执行到断点位置
在这里插入图片描述

然后在左侧的方法调用栈中,一个一个找,是哪个地方调用了onEvent并且进行了try catch异常捕捉
在这里插入图片描述
找到使用了try catch的实际的调用处,如图所示
catch中通过判断listener的isFailOnException()来控制是否抛出异常

由断点可以看出,listener对象是ProcessCompletedListenerDelegate
在这里插入图片描述
在这里插入图片描述
由此可见isFailOnException总是返回false,所以一直不会将异常抛出

解决办法

我们可以创建一个CustomProcessCompletedListenerDelegate自定义子类继承该类,然后重新isFailOnException方法,但是问题是如何将spring环境中的ProcessCompletedListenerDelegate替换成我们的自定义子类
那么我们就看ProcessCompletedListenerDelegate类是什么时候创建出来的,在创建时,替换成我们自定义的类

有2个办法:

  1. ProcessCompletedListenerDelegate类的构造器上面打断点(小提示:如果遇到想给构造器打断点,但是没有写构造器的情况下,就在类名所在行打断点),然后重启项目,等执行到断点行的时候,再次查看方法调用栈,找到什么时候创建的该类
  2. 直接alt + F7,或者右键类名点Find Usages查找使用地方

在这里插入图片描述

取巧一点的方法是先用方式2,看看使用的地方多不多,如果很多无法确定具体使用的地方,那么在用方法1

这里可以直接使用方法2,找到调用处
在这里插入图片描述

ProcessRunTimeAutoConfiguration的369行在使用,直接点进去

这就好办了,看到了@ConditionOnMissingBean,那么我们可以直接自己注入CustomProcessCompletedListenerDelegate到Spring中来管理就可以

解决代码如下

自定义监听器委托类CustomProcessCompletedListenerDelegate

/**
 * 继承ProcessCompletedListenerDelegate,重写isFailOnException以达目的
 */
public class CustomProcessCompletedListenerDelegate extends ProcessCompletedListenerDelegate {
    public CustomProcessCompletedListenerDelegate(List<ProcessRuntimeEventListener<ProcessCompletedEvent>> processRuntimeEventListeners, ToProcessCompletedConverter processCompletedConverter) {
        super(processRuntimeEventListeners, processCompletedConverter);
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }
}

注入Spring,我这里使用的是SpringBoot

@Configuration
// 如果是spi方式注入,则添加如下这行控制顺序
// @AutoConfigureBefore(ProcessRuntimeAutoConfiguration.class)
public class ProcessCompleteListenerConfig {

    @Bean("registerProcessCompletedListenerDelegate")
    public InitializingBean registerProcessCompletedListenerDelegate(
            RuntimeService runtimeService,
            @Autowired(required = false) List<ProcessRuntimeEventListener<ProcessCompletedEvent>> eventListeners,
            ToProcessCompletedConverter converter) {
        return () -> runtimeService.addEventListener(new CustomProcessCompletedListenerDelegate(getInitializedListeners(eventListeners),
                        converter),
                ActivitiEventType.PROCESS_COMPLETED);
    }

    private <T> List<T> getInitializedListeners(List<T> eventListeners) {
        return eventListeners != null ? eventListeners : Collections.emptyList();
    }


}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值