Apache camel 基于XQuery筛选器设置标头
我有一个路由设置为以批处理模式运行,轮询数千个XML文件。每个元素都在XML结构中加上时间戳,这个dateTime元素用于确定是否应该将XML包含在批处理的进一步处理(XQuery转换)中。由于这是一个批处理路由,它在执行后自行终止 因为路由需要自己关闭,所以我必须确保如果每条消息都被过滤掉,它也会关闭,这就是为什么我不使用过滤器,而是使用Apache camel 基于XQuery筛选器设置标头,apache-camel,Apache Camel,我有一个路由设置为以批处理模式运行,轮询数千个XML文件。每个元素都在XML结构中加上时间戳,这个dateTime元素用于确定是否应该将XML包含在批处理的进一步处理(XQuery转换)中。由于这是一个批处理路由,它在执行后自行终止 因为路由需要自己关闭,所以我必须确保如果每条消息都被过滤掉,它也会关闭,这就是为什么我不使用过滤器,而是使用.choice()语句,并在exchange上设置一个自定义头,该头稍后在一个bean中使用,该bean对匹配项进行分组,并为XQuery准备一个源文档 然而
.choice()
语句,并在exchange上设置一个自定义头,该头稍后在一个bean中使用,该bean对匹配项进行分组,并为XQuery准备一个源文档
然而,我当前的方法需要另一条路径,.choice()
的两个分支都要转发到该路径。这是必要的,因为我似乎不能强迫两条路都继续下去。所以我的问题是:如何摆脱第二条路线?一种方法是在bean中设置过滤器头,但我担心涉及的开销。我假设Camel中的XQuery过滤器的性能将大大优于POJO,POJO从字符串构建XML文档并对其运行XQuery
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();
你不想在这里帮忙吗?
我的意思是:
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");
}
};
}
我花了很长时间才回到这个问题上来,因为我刚刚回到项目的这一部分。您提供的第二个代码示例非常有效,正是我所需要的。整个
.choice()
语句末尾的一个简单的.end()
语句终止所有分支。您最初的第一个代码部分有两条不正确且无法编译的.end()
语句。我相应地修改了它。再次感谢。