Camel - 流缓存没有缓存/无法转换?

时间:2014-12-10 14:38:03

标签: java apache-camel

在阅读一次之后,我似乎正在失去我的“身体”。请注意,我正在使用Camel的流缓存,并且输入是来自http组件的json文件。我有一个处理器,代码如下。

    log.debug("Body Type: " + exchange.getIn().getBody().getClass().getCanonicalName());
    log.debug("In msg1:"  + exchange.getIn().getBody(String.class));
    log.debug("In msg2:"  + exchange.getIn().getBody(String.class));

我期望在这里看到msg1和msg2是相同的输出,但是msg2返回一个空字符串(非空)。以下是TRACE级别的日志。

1- DEBUG com.mycompany.MyProcessor : Body Type: org.apache.camel.converter.stream.InputStreamCache
2- TRACE org.apache.camel.impl.converter.DefaultTypeConverter : Converting org.apache.camel.converter.stream.InputStreamCache -> java.lang.String with value: org.apache.camel.converter.stream.InputStreamCache@780a5cef
3- TRACE org.apache.camel.impl.converter.DefaultTypeConverter : Using converter: StaticMethodTypeConverter: public static java.lang.String org.apache.camel.converter.IOConverter.toString(java.io.InputStream,org.apache.camel.Exchange) throws java.io.IOException to convert [class org.apache.camel.converter.stream.InputStreamCache=>class java.lang.String]
4- DEBUG com.mycompany.MyProcessor : In msg1:{myJson}
5- TRACE org.apache.camel.impl.converter.DefaultTypeConverter : Converting org.apache.camel.converter.stream.InputStreamCache -> java.lang.String with value: org.apache.camel.converter.stream.InputStreamCache@780a5cef
6- TRACE org.apache.camel.impl.converter.DefaultTypeConverter : Using converter: StaticMethodTypeConverter: public static java.lang.String org.apache.camel.converter.IOConverter.toString(java.io.InputStream,org.apache.camel.Exchange) throws java.io.IOException to convert [class org.apache.camel.converter.stream.InputStreamCache=>class java.lang.String]
7- DEBUG com.mycompany.MyProcessor : In msg2:

日志中要注意的事项:

  • 第1行 - 正文类型正确显示缓存的输入流
  • 第4行转换为字符串确实可以生成msg1,即使第3行(转换代码)似乎因IOException而失败
  • 第6行 - 转换失败,但重要的是要注意主体仍然是缓存的流。
  • 第7行 - 我的消息丢失了。

那么msg2去了哪里?

修改

除了彼得的答案之外,还有一些事情需要提及:

Camel的MessageHelper静态类有两个有用的功能:

  • resetStreamCache
  • extractBodyAsString

这两种情况都有助于解决这种情况

5 个答案:

答案 0 :(得分:7)

使用流缓存允许您在不同的处理器中多次读取流但在同一处理器中只能一次

我测试过:

ModelCamelContext context = new DefaultCamelContext();
context.setStreamCaching(true); //!!
// ...

from("direct:start")
    .to("http://ip.jsontest.com/?callback=showMyIP")
    .process(new MyProcessor())
    .process(new MyProcessor());

public class MyProcessor implements Processor {
    private static final Logger LOG = LoggerFactory.getLogger(HttpStreamCache.MyProcessor.class);
    @Override
    public void process(final Exchange exchange) throws Exception {
        LOG.info("***** Body Type: " + exchange.getIn().getBody().getClass().getCanonicalName());
        LOG.info("***** In msg1  : " + exchange.getIn().getBody(String.class));
        LOG.info("***** In msg2  : " + exchange.getIn().getBody(String.class));
    }
};

打印:

INFO  ***** Body Type: org.apache.camel.converter.stream.InputStreamCache
INFO  ***** In msg1  : showMyIP({"ip": "00.000.000.00"});

INFO  ***** In msg2  : 
INFO  ***** Body Type: org.apache.camel.converter.stream.InputStreamCache
INFO  ***** In msg1  : showMyIP({"ip": "00.000.000.00"});

INFO  ***** In msg2  :  

答案 1 :(得分:2)

我相信你的问题不在于输入流消失了,而是它的读者位置在最后消费点,在这种情况下,在流的末尾。

你可以使用一个流"倒带"可以将您的读者带到流的开头的方法 - 仅当流支持它时。

这是一个提供此类重置器的scala代码:

object StreamResetter extends Processor {
  import org.apache.camel.util.MessageHelper
  import org.apache.camel.Exchange

  override def process(exchange: Exchange): Unit = MessageHelper.resetStreamCache(exchange.getIn)
}

,在您的路线上,就在第二次日志调用之前,您可以使用

process(StreamResetter)

问候。

答案 2 :(得分:0)

如果您的JSON输入流的内容不是非常大,您可以将输入流转换为ByteArrayInputStream,这样您就可以在任何Processor中多次读取它。希望有所帮助。

答案 3 :(得分:0)

我的工作示例:

from("direct:secondRoute")
     .to("callOtherService")
     .log("RESPONSE: ${body}")  
     .process(exchange -> {
        InputStream in = exchange.getIn().getBody(InputStream.class);
        in.reset();
     });

from("direct:firstRoute")
     .to(direct:secondRoute)
     .convertBodyTo(String.class); 

答案 4 :(得分:0)

如果使用 spring boot,只需启用流缓存。

camel.springboot.stream-caching-enabled=true