使用apache camel进行多文件i / o

时间:2017-02-07 08:33:53

标签: apache-camel

我的要求如下:我需要解压缩文件并从解压缩的xml文件中读取元数据信息。这将在xmlToObjectMapper中完成。现在我需要使用位于zip文件中的多个其他xml的数据来丰富元数据。这意味着我必须解压缩它们读取它们并将信息附加到我的MetadataHolder对象。我想在注释行pollEnrich中实现这一点。

from("file://{{first.directory}}?noop=true&idempotent=true")
        .split(new ZipSplitter())
            .streaming()
                .choice()
                    .when(header("zipFileName").isEqualTo("metadata.xml"))
                        .multicast()
                            .to("file://{{first.directory}}/Working?fileName=$simple{file:onlyname.noext}/${header.zipFileName}")
                            .pipeline()
                                .convertBodyTo(String.class, StandardCharsets.ISO_8859_1.name())
                                .bean("xmlToObjectMapper", "readAllRequiredMetadata")
                                //.pollEnrich("", 0, new MetadataHolderAggregationStrategy())
                            .end()
                        .end()
                .end()
            .to("file://{{first.directory}}/Working?fileName=$simple{file:onlyname.noext}/${header.zipFileName}")
        .end()
    .end()
    ;

但现在我被困了,因为我得到了以下的堆栈跟踪:

org.apache.camel.InvalidPayloadException: No body available of type: java.lang.String but has value: org.apache.camel.dataformat.zipfile.ZipInputStreamWrapper@2c52254b of type: org.apache.camel.dataformat.zipfile.ZipInpu
tStreamWrapper on: Message[id]. Caused by: Error during type conversion from type: java.lang.String to the required type: java.lang.String with value [Body is instance of java.io.I
nputStream] due java.io.IOException: Stream closed. Exchange[id]. Caused by: [org.apache.camel.TypeConversionException - Error during type conversion from type: java.lang.String to
 the required type: java.lang.String with value [Body is instance of java.io.InputStream] due java.io.IOException: Stream closed]

我认为多播会隐式缓存流并将其发送到所有端点......

所以有人能告诉我为什么会这样吗?我的需求解决方案是有效的方式还是我必须将需求分成多个路由?

EDIT1:

我通过向路由添加.streamCaching()解决了异常问题。由于其他问题,我不得不改变原来的路线。

from("file://{{first.directory}}?noop=true&idempotent=true")
        .streamCaching()
        .split(new ZipSplitter())
            .streaming()
                .choice()
                    .when(header("zipFileName").isEqualTo("metadata.xml"))
                        .multicast()
                            .to("file://{{first.directory}}/Working?fileName=$simple{file:onlyname.noext}/${header.zipFileName}")
                            .pipeline()
                                .convertBodyTo(String.class, StandardCharsets.ISO_8859_1.name())
                                .bean("xmlToObjectMapper", "readAllRequiredMetadata")
                                .pollEnrich("file://{{second.directory}}?&noop=true&idempotent=true", 0, new MetadataHolderAggregationStrategy())
                            .end()
                        .end()
                    .endChoice()
                    .otherwise()
                        .to("file://{{first.directory}}/Working?fileName=$simple{file:onlyname.noext}/${header.zipFileName}")
                .end()
        .end()
    .end()
    ;

但现在我遇到了pollEnrich的问题。我MetadataHolderAggregationStrategy中的newExchange始终为null。我怎么解决这个问题?

EDIT2:

最后我找到了解决方案。我必须使用enrich而不是pollEnrich并在java(readAllRequiredMetadata2)中实现整个i / o。我的最终解决方案如下:

from("file://{{first.directory}}?noop=true&idempotent=true")
        .streamCaching()
        .split(new ZipSplitter())
            .streaming()
                .choice()
                    .when(header("zipFileName").isEqualTo("metadata.xml"))
                        .multicast()
                            .to("file://{{first.directory}}/Working?fileName=$simple{file:onlyname.noext}/${header.zipFileName}")
                            .pipeline()
                                .convertBodyTo(String.class, StandardCharsets.ISO_8859_1.name())
                                .bean("xmlToObjectMapper", "readAllRequiredMetadata")
                                .enrich("direct:readResources", 0, new MetadataHolderAggregationStrategy())
                                //Go on processing the enriched metadata
                            .end()
                        .end()
                    .endChoice()
                    .otherwise()
                        .to("file://{{first.directory}}/Working?fileName=$simple{file:onlyname.noext}/${header.zipFileName}")
                .end()
        .end()
    .end()
    ;

from("direct:readResources")
   .bean("xmlToObjectMapper", "readAllRequiredMetadata2")
.end()
;

1 个答案:

答案 0 :(得分:0)

对于类似流的数据,您可能需要使用流缓存。它默认是关闭的,所以第二个端点不会拥有它,因为第一个端点已经读过它。您可以在那里查看更多详细信息:http://camel.apache.org/stream-caching.html