Apache Camel:缓存的流文件删除导致文件未找到错误

时间:2017-11-23 10:59:58

标签: java apache-camel

情境: 我正在尝试流和处理一些大型xml文件。这些文件是异步发送的。

producerTemplate.sendBodyAndHeaders(endpointUri, inStream, ImmutableMap.of(JOBID_PROPERTY, importJob.getId()));

我需要批处理所有文件输入流,通过使用xpath探测文件来识别文件,并根据其内容对它们进行重新排序。我有以下路线:

   from("direct:route1")
        .streamCaching()
        .choice()
        .when(xpath("//Tag1"))             .setHeader("execOrder", constant(3))    .setHeader("xmlRoute", constant( "direct:some-route"))
        .when(xpath("//Tag2"))             .setHeader("execOrder", constant(1))    .setHeader("xmlRoute", constant( "direct:some-other-route"))
        .when(xpath("//Tag3"))             .setHeader("execOrder", constant(2))    .setHeader("xmlRoute", constant( "direct:yet-another-route"))
        .otherwise()
            .to("direct:somewhereelse")
        .end()
        .resequence(header("execOrder"))
        .batch(new BatchResequencerConfig(300, 10000L))
        .allowDuplicates()
        .recipientList(header("xmlRoute"))

运行我的代码时出现以下错误:

   2017-11-23 11:43:13.442  INFO 10267 --- [ - Batch Sender] c.w.n.s.m.DefaultImportJobService        : Updating entity ImportJob with id 5a16a61803af33281b22c716
   2017-11-23 11:43:13.451  WARN 10267 --- [ - Batch Sender] org.apache.camel.processor.Resequencer   : Error processing aggregated exchange: Exchange[ID-int-0-142-bcd-wsint-pro-59594-1511433568520-0-20]. Caused by: [org.apache.camel.RuntimeCamelException - Cannot reset stream from file /var/folders/dc/fkrgdrnx6txbg7jfdjd_58mm0000gn/T/camel/camel-tmp-39abaae8-9bdd-435a-b63d-299ad8b06415/cos1499080503439465502.tmp]

   org.apache.camel.RuntimeCamelException: Cannot reset stream from file /var/folders/dc/fkrgdrnx6txbg7jfdjd_58mm0000gn/T/camel/camel-tmp-39abaae8-9bdd-435a-b63d-299ad8b06415/cos1499080503439465502.tmp
   at org.apache.camel.converter.stream.FileInputStreamCache.reset(FileInputStreamCache.java:91)

我已经读过here,当调用XPathBuilder.getDocument()时,FileInputStreamCache被关闭,临时文件被删除,因此当XPathBuilder想要重置InputStream时,你会得到FileNotFoundException < / p>

解决方案似乎是禁用假脱机到磁盘:

camelContext.getStreamCachingStrategy().setSpoolThreshold(-1);

但是,由于RAM的限制,我不想这样做,即文件最多可达600MB,我不想将它们保存在内存中。任何想法如何解决问题?

2 个答案:

答案 0 :(得分:2)

重新定序器是一个双腿模式(有状态)并且将导致原始交换事先完成,因为它在重新排序时将副本保留在内存中,直到满足间隙并以新顺序发送消息

由于您的输入流来自某些HTTP服务,因此预先关闭该重定序器可以输出交换。

按照建议首先存储到本地磁盘,然后让重新排序器对其进行操作,或找到不使用重新排序器的方法。

答案 1 :(得分:1)

我最终做了克劳斯和里卡多的建议。我做了一个单独的路由,将文件保存到磁盘。然后另一个探测文件并根据固定顺序重新排序交换。

String xmlUploadDirectory = "file://" + Files.createTempDir().path + "/xmls?noop=true"

from("direct:route1")
    .to(xmlUploadDirectory)

from(xmlUploadDirectory)
    .choice()
    .when(xpath("//Tag1")).setHeader("execOrder", constant(3)).setHeader("xmlRoute", constant( "direct:some-route"))
    .when(xpath("//Tag2")).setHeader("execOrder", constant(1)).setHeader("xmlRoute", constant( "direct:some-other-route"))
    .when(xpath("//Tag3")).setHeader("execOrder", constant(2)).setHeader("xmlRoute", constant( "direct:yet-another-route"))
    .otherwise()
    .to("direct:somewhereelse")
    .end()
    .to("direct:resequencing")

from("direct:resequencing")
    .resequence(header("execOrder"))
    .batch(new BatchResequencerConfig(300, 10000L))
    .allowDuplicates()
    .recipientList(header("xmlRoute"))