基于XQuery过滤器设置标头

时间:2013-05-29 08:18:54

标签: apache-camel

我有一条路由设置为以批处理模式运行,轮询了数千个XML文件。每个都在XML结构中加上时间戳,这个dateTime元素用于确定XML是否应该包含在批处理的进一步处理(XQuery转换)中。由于这是批处理路由,因此在执行后会自行终止。

因为路由需要自行关闭,所以我必须确保它在每个消息都被过滤掉时也会关闭,这就是为什么我不使用过滤器而是使用.choice()语句而是设置自定义标头的原因。稍后在bean中使用的交换,它将匹配并为XQuery准备单个源文档。

但是,我目前的方法需要第二条路线,.choice()的两个分支都转发到。这是必要的,因为我似乎不能强迫两条路径继续。所以我的问题是:如何摆脱这第二条路线?一种方法是在bean中设置过滤器头,但我担心所涉及的开销。我假设Camel中的XQuery过滤器将大大优于从字符串构建XML文档并对其运行XQuery的POJO。

from(sourcePath + "?noop=true" + "&include=.*.xml")
        .choice()
            .when()
                .xquery("[XQuery Filter]")
                .setHeader("Filtered", constant(false))
                .to("direct:continue")
            .otherwise()
                .setHeader("Filtered", constant(true))
                .to("direct:continue")
.end();

from("direct:continue")
        .routeId(forwarderRouteID)
        .aggregate(aggregationExpression)
            .completionFromBatchConsumer()
            .completionTimeout(DEF_COMPLETION_TIMEOUT)
            .groupExchanges()
        .bean(new FastQueryMerger(), "group")
        .to("xquery:" + xqueryPath)
        .bean(new FileModifier(interval), "setFileName")
        .to(targetPath)
        .process(new Processor() {
                @Override
                public void process(Exchange exchange) throws Exception {
                    new RouteTerminator(routeID, exchange.getContext()).start();
                    new RouteTerminator(forwarderRouteID, exchange.getContext()).start();
                }
            })
.end();

1 个答案:

答案 0 :(得分:1)

不会.end()在这里帮忙吗? 我的意思是:

from(sourcePath + "?noop=true" + "&include=.*.xml")
    .choice()
        .when()
            .xquery("[XQuery Filter]")
            .setHeader("Filtered", constant(false)).end()
        .otherwise()
            .setHeader("Filtered", constant(true)).end()
    .aggregate(aggregationExpression)
        .completionFromBatchConsumer()
        .completionTimeout(DEF_COMPLETION_TIMEOUT)
        .groupExchanges()
    .bean(new FastQueryMerger(), "group")
    .to("xquery:" + xqueryPath)
    .bean(new FileModifier(interval), "setFileName")
    .to(targetPath)
    .process(new Processor() {
            @Override
            public void process(Exchange exchange) throws Exception {
                new RouteTerminator(routeID, exchange.getContext()).start();
                new RouteTerminator(forwarderRouteID, exchange.getContext()).start();
            }
        });

快速测试了下面的一个并且它有效:

@Produce(uri = "direct:test")
protected ProducerTemplate testProducer;
@EndpointInject(uri = "mock:test-first")
protected MockEndpoint testFirst;
@EndpointInject(uri = "mock:test-therest")
protected MockEndpoint testTheRest;
@EndpointInject(uri = "mock:test-check")
protected MockEndpoint testCheck;

@Test
public void test() {
    final String first = "first";
    final String second = "second";
    testFirst.setExpectedMessageCount(1);
    testTheRest.setExpectedMessageCount(1);
    testCheck.setExpectedMessageCount(2);
    testProducer.sendBody(first);
    testProducer.sendBody(second);
    try {
        testFirst.assertIsSatisfied();
        testTheRest.assertIsSatisfied();
        testCheck.assertIsSatisfied();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

@Override
protected RouteBuilder createRouteBuilder() {
    return new RouteBuilder() {
        public void configure() {
            from("direct:test")
                .choice()
                    .when(body().isEqualTo("first")).to("mock:test-first")
                    .otherwise().to("mock:test-therest").end()
                    .to("mock:test-check");
        }
    };
}