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

Apache Camel 4.3.0与4.9.0异常重试行为差异及兼容方案咨询

Apache Camel 4.3.0至4.9.0异常处理行为变更及重试实现咨询

我正在进行基于Spring Boot 3.4.0、Java 23的Apache Camel路由迁移项目,使用全局onException和路由级doTry/doCatch异常处理器。发现Camel 4.3.0与4.9.0的异常重试行为存在差异:

  • 在4.3.0中,未被路由级处理器捕获的ClassCastException会触发全局处理器并完成自动重试;
  • 在4.9.0中,全局onException处理器未触发,无法捕获该异常。

查阅官方文档得知,存在路由级doTry/doCatch处理器时全局onException不再触发。现咨询:

  1. 该行为是否在Camel 4.3.0至4.9.0版本间发生变更?
  2. 在Camel 4.9.0中如何通过原生机制实现自动重试,避免手动迭代?

测试代码

package com.apache.camel.test_exception;

import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;

@Component
public class ExceptionTest extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        
        onException(Exception.class)
            .handled(true)          
            .log("Caught exception")
            .maximumRedeliveries(3)
            .redeliveryDelay(3000)
            .retryAttemptedLogLevel(LoggingLevel.WARN)
            .retriesExhaustedLogLevel(LoggingLevel.WARN)
            .log("Exception Handled")
        .end();
        
        restConfiguration().component("servlet").scheme("http").port(8080);
        
        rest("/service/api/v1")
            .get("/testException")
            .routeId("rest-exception")
            .to("direct:exceptionRoute");
        
        from("direct:exceptionRoute")
            .routeId("exception-route")
            .log("Received request to test exception")
            .doTry()
                .throwException(new ClassCastException())       
            .doCatch(NullPointerException.class)
                .log("NullPointer Exception Caught")
            .endDoTry()
            .log("Route ended")
        .end();         
    } 
}

Camel 4.3.0日志

2024-12-14T10:52:33.699+05:30 INFO 16524 --- [test-exception] [nio-8080-exec-1] exception-route : Received request to test exception
2024-12-14T10:52:33.704+05:30 WARN 16524 --- [test-exception] [nio-8080-exec-1] o.a.c.p.e.DefaultErrorHandler : Failed delivery for (MessageId: A1B32AE5C117F9F-0000000000000000 on ExchangeId: A1B32AE5C117F9F-0000000000000000). On delivery attempt: 0 caught: java.lang.ClassCastException
2024-12-14T10:52:36.720+05:30 INFO 16524 --- [test-exception] [nio-8080-exec-1] exception-route : Received request to test exception
2024-12-14T10:52:36.720+05:30 WARN 16524 --- [test-exception] [nio-8080-exec-1] o.a.c.p.e.DefaultErrorHandler : Failed delivery for (MessageId: A1B32AE5C117F9F-0000000000000000 on ExchangeId: A1B32AE5C117F9F-0000000000000000). On delivery attempt: 1 caught: java.lang.ClassCastException
2024-12-14T10:52:39.731+05:30 INFO 16524 --- [test-exception] [nio-8080-exec-1] exception-route : Received request to test exception
2024-12-14T10:52:39.731+05:30 WARN 16524 --- [test-exception] [nio-8080-exec-1] o.a.c.p.e.DefaultErrorHandler : Failed delivery for (MessageId: A1B32AE5C117F9F-0000000000000000 on ExchangeId: A1B32AE5C117F9F-0000000000000000). On delivery attempt: 2 caught: java.lang.ClassCastException
2024-12-14T10:52:42.734+05:30 INFO 16524 --- [test-exception] [nio-8080-exec-1] exception-route : Received request to test exception
2024-12-14T10:52:42.735+05:30 WARN 16524 --- [test-exception] [nio-8080-exec-1] o.a.c.p.e.DefaultErrorHandler : Failed delivery for (MessageId: A1B32AE5C117F9F-0000000000000000 on ExchangeId: A1B32AE5C117F9F-0000000000000000). On delivery attempt: 3 caught: java.lang.ClassCastException
2024-12-14T10:52:42.741+05:30 INFO 16524 --- [test-exception] [nio-8080-exec-1] rest-exception : Caught exception
2024-12-14T10:52:42.741+05:30 INFO 16524 --- [test-exception] [nio-8080-exec-1] rest-exception : Exception Handled

Camel 4.9.0日志

2024-12-14T11:16:55.864+05:30 INFO 20908 --- [test-exception] [ main] c.a.c.t.TestExceptionApplication : Started TestExceptionApplication in 3.152 seconds (process running for 3.61)
2024-12-14T11:19:32.081+05:30 INFO 20908 --- [test-exception] [nio-8080-exec-1] exception-route : Received request to test exception


问题解答

1. 版本间行为变更确认

是的,该行为是Camel 4.3.0到4.9.0之间的有意变更。在早期版本中,doTry/doCatch未捕获的异常会冒泡到全局onException处理器,但从Camel 4.4.x版本开始,官方调整了异常处理优先级:当路由中存在doTry/doCatch块时,未被捕获的异常不再触发全局onException,而是由路由的默认错误处理器(如果未禁用)处理,或者直接抛出未捕获异常。这一变更旨在明确异常处理的边界,避免全局处理器意外拦截局部未处理的异常。

2. Camel 4.9.0中实现自动重试的原生方案

针对你的场景,有三种原生方式可以实现自动重试:

方案一:在doTry块内配置局部重试规则

直接在doTry块内部添加错误处理器配置,针对块内步骤触发重试:

from("direct:exceptionRoute")
    .routeId("exception-route")
    .log("Received request to test exception")
    .doTry()
        .errorHandler(defaultErrorHandler()
            .maximumRedeliveries(3)
            .redeliveryDelay(3000)
            .retryAttemptedLogLevel(LoggingLevel.WARN))
        .throwException(new ClassCastException())       
    .doCatch(NullPointerException.class)
        .log("NullPointer Exception Caught")
    .doCatch(ClassCastException.class)
        .log("ClassCast Exception Caught after retries")
    .endDoTry()
    .log("Route ended")
.end();

方案二:在路由中复用全局异常配置

将全局异常处理逻辑显式应用到目标路由,覆盖doTry的默认隔离行为:

// 定义全局异常模板
OnExceptionDefinition globalException = onException(Exception.class)
    .handled(true)          
    .log("Caught exception")
    .maximumRedeliveries(3)
    .redeliveryDelay(3000)
    .retryAttemptedLogLevel(LoggingLevel.WARN)
    .retriesExhaustedLogLevel(LoggingLevel.WARN)
    .log("Exception Handled");

// 在路由中应用全局异常配置
from("direct:exceptionRoute")
    .routeId("exception-route")
    .log("Received request to test exception")
    .onException(Exception.class).inheritErrorHandler(globalException).end()
    .doTry()
        .throwException(new ClassCastException())       
    .doCatch(NullPointerException.class)
        .log("NullPointer Exception Caught")
    .endDoTry()
    .log("Route ended")
.end();

方案三:禁用doTry的错误处理器隔离

通过inheritErrorHandler(false)取消doTry块的错误处理器隔离,让未捕获异常冒泡到路由级错误处理器,进而触发全局onException:

from("direct:exceptionRoute")
    .routeId("exception-route")
    .log("Received request to test exception")
    .doTry().inheritErrorHandler(false)
        .throwException(new ClassCastException())       
    .doCatch(NullPointerException.class)
        .log("NullPointer Exception Caught")
    .endDoTry()
    .log("Route ended")
.end();

注意:此方式需确保路由的默认错误处理器未被禁用,且全局onException配置符合预期。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:14:53