情境: 我正在尝试流和处理一些大型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,我不想将它们保存在内存中。任何想法如何解决问题?
答案 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"))