Java 从组合路线获得准确响应
我有一个动态路由创建者web应用程序。根据流程设计,我制作了骆驼路线。路由可能包含多播、筛选器、聚合、处理器等。在通过UI设计流后,我的路由创建如下:Java 从组合路线获得准确响应,java,apache-camel,Java,Apache Camel,我有一个动态路由创建者web应用程序。根据流程设计,我制作了骆驼路线。路由可能包含多播、筛选器、聚合、处理器等。在通过UI设计流后,我的路由创建如下: from("seda:start").routeId("idx") .multicast() .to("direct:a", "direct:b", "direct:c") .parallelProcessing() .end(); from("direct:a").transform(constant(
from("seda:start").routeId("idx")
.multicast()
.to("direct:a", "direct:b", "direct:c")
.parallelProcessing()
.end();
from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");
from("direct:merge")
.aggregate(new MyAggregationStrategy()).constant(true).completionSize(3)
.to("mock:end");
from("seda:start").routeId("idx")
.multicast()
.to("direct:a", "direct:b", "direct:c", "direct:d", "direct:e")
.parallelProcessing()
.end();
from("direct:a").transform(constant("A")).delay(1000).to("direct:merge1");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge1");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge2");
from("direct:d").transform(constant("D")).delay(1000).to("direct:merge2");
from("direct:e").transform(constant("E")).delay(1000).to("mock:anywhere");
from("direct:merge1").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("direct:merge3");
from("direct:merge2").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("direct:merge3");
from("direct:merge3").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("mock:end");
我有一个API向用户提供此路由的结果。当我使用InOut MEP执行此路由时,响应为“C”,但mock:end对“ABC”表示满意:
MockEndpoint mock = getMockEndpoint("mock:end");
mock.expectedBodiesReceived("ABC"); //works as expected
String reply = template.requestBody("seda:start", "", String.class);
assertEquals("ABC", reply); //it returns 'C', but I expect 'ABC'
assertMockEndpointsSatisfied();
如何更改代码以通过同步调用获得聚合结果?代码如下:
public class ResponseTest extends CamelTestSupport {
@Test
public void testAsyncInOut() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:end");
mock.expectedBodiesReceived("ABC"); //works as expected
String reply = template.requestBody("seda:start", "", String.class);
assertEquals("ABC", reply); //it returns 'C', but I expect 'ABC'
assertMockEndpointsSatisfied();
}
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("seda:start").routeId("idx")
.multicast()
.to("direct:a", "direct:b", "direct:c")
.parallelProcessing()
.end();
from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");
from("direct:merge")
.aggregate(new MyAggregationStrategy()).constant(true).completionSize(3)
.to("mock:end");
}
};
}
class MyAggregationStrategy implements AggregationStrategy {
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
if (oldExchange == null) {
// this is the first time so no existing aggregated exchange
return newExchange;
}
// append the new word to the existing
String body = newExchange.getIn().getBody(String.class);
String existing = oldExchange.getIn().getBody(String.class);
oldExchange.getIn().setBody(existing + body);
return oldExchange;
}
}
}
编辑
将消息多播到5个不同的端点并不意味着所有消息将在以后聚合。所以我不能在多播定义中使用聚合策略。其中一些可能被用于另一种工作。流定义可能如下所示:
在多播消息发送到“a”、“b”、“c”、“d”、“e”端点之后,“a”和“b”可以聚合在一起(“direct:merge1”),“c”和“d”聚合在一起(“direct:merge2”),“e”可以用于其他用途。
最终的聚合器将聚合为“direct:merge1”和“direct:merge2”
至“直接:合并3”。所有这些端点都是动态创建的('direct:a'、'direct:b'、'direct:c'、'direct:d'、'direct:e'、'direct:merge1'、'direct:merge2'、'direct:merge3')。此场景将按如下方式创建:
from("seda:start").routeId("idx")
.multicast()
.to("direct:a", "direct:b", "direct:c")
.parallelProcessing()
.end();
from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");
from("direct:merge")
.aggregate(new MyAggregationStrategy()).constant(true).completionSize(3)
.to("mock:end");
from("seda:start").routeId("idx")
.multicast()
.to("direct:a", "direct:b", "direct:c", "direct:d", "direct:e")
.parallelProcessing()
.end();
from("direct:a").transform(constant("A")).delay(1000).to("direct:merge1");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge1");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge2");
from("direct:d").transform(constant("D")).delay(1000).to("direct:merge2");
from("direct:e").transform(constant("E")).delay(1000).to("mock:anywhere");
from("direct:merge1").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("direct:merge3");
from("direct:merge2").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("direct:merge3");
from("direct:merge3").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("mock:end");
当我向seda发送消息时:开始,我期望ABDC,但我得到了“E”。有没有办法获取最终聚合消息(“ABDC”)?以下是测试方法:
@Test
public void testAsyncInOut() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:end");
mock.expectedBodiesReceived("ABDC"); //works as expected
String reply = template.requestBody("seda:start", "", String.class);
assertEquals("ABDC", reply); //it returns 'E' because of default multicast behavior, but I expect 'ABDC'
assertMockEndpointsSatisfied();
}
从
多播
:
默认情况下,Camel将使用最后一个回复作为传出消息
如果要将多播结果聚合到单个消息中,请在多播定义中声明
@Override
public void configure() throws Exception {
from("seda:start").routeId("idx")
.multicast(new MyAggregationStrategy()) //Put the Aggregation Strategy here!
.to("direct:a", "direct:b", "direct:c")
.parallelProcessing()
.end();
from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");
from("direct:merge")
.to("mock:end");
}
请注意,您的模拟端点现在将被调用3次,因为聚合直到稍后才会发生。您需要相应地修改测试。谢谢您的回答,但我想我无法清楚地解释我的问题。我不能在多播定义中使用聚合策略。由于根据我在编辑中解释的流程设计,聚合消息中可能不包含某些消息,因此我认为您可以将调用嵌套到
多播(new MyAggregationStrategy())
,以获得所需的结果。