骆驼交换机体内的原始消息丢失了

时间:2014-03-12 19:11:15

标签: java apache-camel

我有一条骆驼路线,如下所示,是交易。

 from("jms:queue:start")
     .transacted()
     .bean(new FirstDummyBean(), "setBodyToHello")
     .bean(new SecondDummyBean(), "setBodyToWorld")
     .to("jms:queue:end")

正如其名称所示的bean方法,将body设置为" Hello"和"世界"分别

我还有一个onException子句设置以及如下:

onException(Exception.class)
    .useOriginalMessage()
    .handled(true)
    .to("jms:queue:deadletter")
    .markRollbackOnlyLast(); 

假设,我在队列中删除了一条消息" start"身体为"测试信息"。在FirstDummyBean中成功处理之后,我在SecondDummyBean中抛出一个RuntimeException。 我期待看到实际的消息或(原始消息内容完整,即#34;测试消息")被发送到我的死信队列。

然而,deadletter queue上的消息内容是" Hello"。

为什么会这样?

我正在使用apache camel 2.10.0。

也可以有人提供有关如何同时使用errorhandler和onexception子句的更多信息。 该文件说:

  

如果您使用交易的DSL标记了一条路线,那么Camel   将自动使用TransactionErrorHandler。它将尝试查找global / per   路由配置错误处理程序并使用它,如果它是TransactionErrorHandlerBuilder
  实例。如果没有,Camel会自动创建一个临时的TransactionErrorHandler   否决了默认的错误处理程序。这是约定优于配置。

如何在JavaDSL中使用transactionerrorhandler的例子很棒。

1 个答案:

答案 0 :(得分:1)

我在非交易示例中看到了这一点,看来useOriginalMessage()确实使用了原始交换,但是如果您修改了这个引用的任何对象,那么您仍然可以进行修改。 useOriginalMessage似乎没有返回队列来获取原始数据。

显示问题的示例代码

以下代码包含一组演示问题的路线。定时路由将包含ArrayList String的{​​{1}}发送到第二条路由读取的队列。第二条路由将消息传递给"Test message",这会更改列表的内容。接下来,消息将转到ModifyBody,并抛出TriggerException。这由RuntimeException路由处理,尽管使用了onException,但仍会传递更新的正文。

useOriginalMessage

解决方法

如果使用下面的代码替换import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.camel.spring.SpringRouteBuilder; import org.springframework.stereotype.Component; @Component public class TimedRoute extends SpringRouteBuilder { private static final String QUEUE = "jms:a.queue"; private static final String QUEUE2 = "jms:another.queue"; // The message that will be sent on the route private static final ArrayList<String> payLoad = new ArrayList<String>( Arrays.asList("test message")); public static class ModifyBody { public List<String> modify(final List<String> list) { final List<String> returnList = list; returnList.clear(); returnList.add("Hello"); return returnList; } } public static class TriggerException { public List<String> trigger(final List<String> list) { throw new RuntimeException("Deliberate"); } } @Override public void configure() throws Exception { //@formatter:off onException(Exception.class) .useOriginalMessage() .log("Exception: ${body}") .handled(true) .setHeader("exception", constant("exception")) .to(QUEUE2); // Timed route to send the original message from("timer://foo?period=60000") .setBody().constant(payLoad) .to(QUEUE); // Initial processing route - this modifies the body. from(QUEUE) .log("queue ${body}") .bean(new ModifyBody()) .log("after firstDummyBean: ${body}") .bean(new TriggerException()) .stop(); // Messages are send here by the exception handler. from(QUEUE2) .log("queue2: ${body}") .stop(); //@formatter:on } } ,则会在异常处理路径中看到原始消息。

ModifyBody

通过将正文更改为列表,原始public static class ModifyBody { public List<String> modify(final List<String> list) { final List<String> returnList = new ArrayList<String>(list); returnList.clear(); returnList.add("Hello"); return returnList; } } 可以保持不变。

执行一般解决方案很尴尬,因为复制机制将取决于您在飞行中的对象。您可能会发现可以扩展Exchange类,为自己提供一些复制对象的自定义DSL。