如何在Camel路由中发送异常邮件后恢复原消息?
解决Camel路由异常处理后恢复原消息体的问题
给你两种可行的解决办法,都能避免修改主流程消息体导致后续处理失败的问题:
方案一:不碰原消息体,单独处理邮件发送(推荐)
这种方式主流程的MyClass实例完全不受影响,邮件发送用独立的子流程处理:
用wireTap异步发邮件(不阻塞主流程)
wireTap会创建一个独立的子Exchange来处理邮件,原Exchange的body保持不变:
onException(BeanValidationException.class) // 把邮件任务扔给独立路由处理 .wireTap("direct:sendValidationErrorMail") .continued(true); // 单独的邮件发送路由 from("direct:sendValidationErrorMail") .setBody(simple("${exception}")) .to("{{route.mail}}"); from("{{route.from}}") .unmarshal(new BindyCsvDataFormat(MyClass.class)) .to("bean-validator:priceFeedValidator") // 这里的body还是原来的MyClass实例,正常继续处理 .log("继续处理Bean: ${body}");
用Processor同步发邮件(不修改原body)
如果需要同步发送邮件,直接在处理器里新建Exchange发邮件,不改动原消息体:
onException(BeanValidationException.class) .process(exchange -> { BeanValidationException exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, BeanValidationException.class); // 新建一个专门发邮件的Exchange Exchange mailExchange = exchange.getContext().createExchange(); mailExchange.getIn().setBody(exception.toString()); // 发送邮件 exchange.getContext().createProducerTemplate().send("{{route.mail}}", mailExchange); }) .continued(true); from("{{route.from}}") .unmarshal(new BindyCsvDataFormat(MyClass.class)) .to("bean-validator:priceFeedValidator") // 继续处理原Bean .log("继续处理Bean: ${body}");
方案二:先存原消息体,发完邮件再恢复
如果一定要修改body来发邮件,可以先把原Bean存到Exchange属性里,发完邮件再恢复回去:
onException(BeanValidationException.class) // 把原body存到Exchange的自定义属性里 .setProperty("originalMyClass", simple("${body}")) // 设置邮件内容为异常信息 .setBody(simple("${exception}")) .to("{{route.mail}}") // 从属性里取出原Bean,恢复body .setBody(exchangeProperty("originalMyClass")) .continued(true); from("{{route.from}}") .unmarshal(new BindyCsvDataFormat(MyClass.class)) .to("bean-validator:priceFeedValidator") // 这里的body已经恢复成MyClass实例了 .log("继续处理Bean: ${body}");
推荐用方案一的wireTap,异步发送邮件不会拖慢主流程,而且完全不用处理消息体的恢复逻辑,最稳妥。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

