从Camel 2.20.1迁移到3.20.1:多层RouteBuilder错误处理问题
Camel 2.20.1 → 3.20.1 迁移:错误处理路由问题解决方案
问题回顾
你有三个层级调用的RouteBuilder,期望RouteBuilderC抛出的异常能被RouteBuilderA的deadLetterChannel错误处理器处理,且仅重发RouteBuilderC的路由部分,而非整个A→B→C链路。旧版的includeRoutes方法已移除,尝试addRoutes无效。
路由结构参考
RouteBuilderA
@Override public void configure() throws Exception { errorHandler(deadLetterChannel("direct:dead") .maximumRedeliveries(2) .redeliveryDelay(1000)); from("direct:A") .to("direct:B"); }
RouteBuilderB
@Override public void configure() throws Exception { from("direct:B") .to("direct:C"); }
RouteBuilderC
@Override public void configure() throws Exception { errorHandler(noErrorHandler()) from("direct:C") .throwException(new RuntimeException("Something went wrong")) .to("direct:end"); }
可行解决方案
方案1:通过全局onException定向重发(推荐)
在RouteBuilderA中定义全局异常捕获规则,指定仅重发RouteBuilderC的端点,同时保留死信通道的最终处理逻辑。异常会沿着调用链传递到RouteBuilderA的异常处理器,直接触发C的重发,无需经过B。
修改RouteBuilderA代码:
@Override public void configure() throws Exception { // 捕获RuntimeException,仅重发RouteBuilderC的端点 onException(RuntimeException.class) .maximumRedeliveries(2) .redeliveryDelay(1000) .retryAttemptedLogLevel(LoggingLevel.WARN) .to("direct:C"); // 重发失败后,将消息转入死信队列 errorHandler(deadLetterChannel("direct:dead") .useOriginalMessage() // 可选,保留原始消息内容 .maximumRedeliveries(0)); // 关闭死信通道自身的重发,因为onException已处理重发逻辑 from("direct:A") .to("direct:B"); }
RouteBuilderB和C保持原有代码不变:
- RouteBuilderB无需添加任何错误处理器,异常会自然向上游传递
- RouteBuilderC的
noErrorHandler()确保异常直接抛出,不被自身路由拦截
方案2:通过doTry/doCatch在中间路由转发异常
如果需要更灵活的异常转发逻辑,可以在RouteBuilderB中捕获异常,直接将消息发送到RouteBuilderA的专用错误处理路由,由其负责重发C:
RouteBuilderB 修改:
@Override public void configure() throws Exception { from("direct:B") .doTry() .to("direct:C") .doCatch(Exception.class) .to("direct:A-error-handler"); // 转发到A的错误处理端点 }
RouteBuilderA 添加错误处理路由:
@Override public void configure() throws Exception { // 原有主路由 from("direct:A") .to("direct:B"); // 专用错误处理路由,负责重发C并处理死信 from("direct:A-error-handler") .errorHandler(deadLetterChannel("direct:dead") .maximumRedeliveries(2) .redeliveryDelay(1000)) .to("direct:C"); }
关键说明
- 避免给RouteBuilderB添加
noErrorHandler(),否则会触发整个A→B→C链路的重发,不符合需求 - RouteBuilderC的
noErrorHandler()是必要的,确保异常不被自身路由拦截,能向上传递 - 方案1更简洁,利用Camel的全局异常处理机制,无需额外路由端点
内容的提问来源于stack exchange,提问作者Quoshak
相关产品推荐
相关产品推荐

