Apache camel 如何拆分消息对其中一条消息执行一些额外的处理并将其聚合回来
我需要根据一些配置文件配置一些驼峰路由 所有配置的路由都需要将消息拆分为一个或两个子消息,然后对第一个子消息执行一些JMS集成工作,然后将JMS应答与可选的第二个消息聚合在一起。在简化的图片中,它将如下所示:Apache camel 如何拆分消息对其中一条消息执行一些额外的处理并将其聚合回来,apache-camel,Apache Camel,我需要根据一些配置文件配置一些驼峰路由 所有配置的路由都需要将消息拆分为一个或两个子消息,然后对第一个子消息执行一些JMS集成工作,然后将JMS应答与可选的第二个消息聚合在一起。在简化的图片中,它将如下所示: message -- > split --> message 1 --> JMS request/reply --> aggregate --> more processing \--> message 2
message -- > split --> message 1 --> JMS request/reply --> aggregate --> more processing
\--> message 2 /
聚合将在完成大小上完成,我可以预先知道它是1还是2,这取决于路由元数据。当出现第二条消息时,在与JMS应答合并之前不需要其他处理
简而言之,我需要一个拆分,然后是一个路由,然后是一个聚合,这是一个非常常见的模式。唯一的特殊性是,如果存在第二条拆分消息,我不需要在将其聚合回来之前对其执行任何操作
在java DSL中,它将如下所示:
from("direct:abc")
// The splitter below will set the JmsIntegration flag
.split().method(MySplitter.class, "split")
.choice()
.when(header("JmsIntegration"))
.inOut("jms:someQueue"))
.otherwise()
// what should I have on here?
.to(???)
.end()
.aggregate(...)to(...);
所以我的问题是:
if
:如果拆分消息需要JMS,则转到JMS,如果不是直接转到聚合器,则转到聚合器。我正在考虑创建一个虚拟处理器,它实际上什么也不做,但在我看来,这是一种幼稚的方法根据您的帖子,您似乎正在尝试将扩展返回与原始消息合并,但您希望向jms端点发送自定义消息。我建议将原始消息存储在bean、缓存或类似的东西中,利用camel的所有转换,然后让聚合策略利用存储返回所需的格式
from("direct:abc")
.split().method(MySplitter.class, "split")
.choice()
.when(header("JmsIntegration"))
.beanRef("MyStorageBean", "storeOriginal")
.convertBodyTo(MyJmsFormat.class)
//This aggregation strategy could have a reference
//to your storage bean and retrieve the instance
.enrich("jms:someQueue", myCustomAggreationStrategyInstance)
.otherwise()
.end()
.aggregate(...)
.to("direct:continueProcessing");
选项2:根据您的评论,您需要“direct:abc端点收到的原始消息可以简化很多。在本例中,我们可以使用camel现有的原始消息存储来检索传递到direct:abc的消息。如果拆分后的消息具有JmsIntegration头,我们将把正文转换为jms调用所需的格式,利用enrich语句进行jms调用,并使用自定义聚合器访问用于调用jms端点的消息、返回的消息和原始消息direct:abc has。如果您的流没有JmsIntegration头,则消息将转到路由中的Otherwise语句,该语句在结束choice语句之前不进行额外处理,然后使用您需要的任何自定义策略将spit消息聚合回一起
from("direct:abc")
.split().method(MySplitter.class, "split")
.choice()
.when(header("JmsIntegration"))
.convertBodyTo(MyJmsFormat.class)
//See aggregationStrategy sample below
.enrich("jms:someQueue", myAggStrat)
.otherwise()
//Non JmsIntegration header messages come here,
//but receive no work and are passed on.
.end()
.aggregate(...)
.to("direct:continueProcessing");
//Your Custom Aggregator
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
//This logic will retrieve the original message passed into direct:abc
Message originalMessage =(Message)exchange.getUnitOfWork().getOriginalInMessage();
//TODO logic for manipulating your exchanges and returning the desired result
}
根据您的帖子,您似乎正在尝试将扩展返回与原始消息合并,但您希望向jms端点发送自定义消息。我建议将原始消息存储在bean、缓存或类似的东西中,利用camel的所有转换,然后让聚合策略利用存储返回所需的格式
from("direct:abc")
.split().method(MySplitter.class, "split")
.choice()
.when(header("JmsIntegration"))
.beanRef("MyStorageBean", "storeOriginal")
.convertBodyTo(MyJmsFormat.class)
//This aggregation strategy could have a reference
//to your storage bean and retrieve the instance
.enrich("jms:someQueue", myCustomAggreationStrategyInstance)
.otherwise()
.end()
.aggregate(...)
.to("direct:continueProcessing");
选项2:根据您的评论,您需要“direct:abc端点收到的原始消息可以简化很多。在本例中,我们可以使用camel现有的原始消息存储来检索传递到direct:abc的消息。如果拆分后的消息具有JmsIntegration头,我们将把正文转换为jms调用所需的格式,利用enrich语句进行jms调用,并使用自定义聚合器访问用于调用jms端点的消息、返回的消息和原始消息direct:abc has。如果您的流没有JmsIntegration头,则消息将转到路由中的Otherwise语句,该语句在结束choice语句之前不进行额外处理,然后使用您需要的任何自定义策略将spit消息聚合回一起
from("direct:abc")
.split().method(MySplitter.class, "split")
.choice()
.when(header("JmsIntegration"))
.convertBodyTo(MyJmsFormat.class)
//See aggregationStrategy sample below
.enrich("jms:someQueue", myAggStrat)
.otherwise()
//Non JmsIntegration header messages come here,
//but receive no work and are passed on.
.end()
.aggregate(...)
.to("direct:continueProcessing");
//Your Custom Aggregator
public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
//This logic will retrieve the original message passed into direct:abc
Message originalMessage =(Message)exchange.getUnitOfWork().getOriginalInMessage();
//TODO logic for manipulating your exchanges and returning the desired result
}
拆分器自动将拆分的交换重新聚合在一起。但是,默认(自2.3版起)聚合策略是返回原始exchange。通过直接在拆分器上指定默认策略,可以轻松地用自己的策略覆盖默认策略。此外,如果您没有可供选择的流,那么使用过滤器就容易得多。例如:
from("direct:abc")
.split().method(MySplitter.class, "split").aggregationStrategy(new MyStrategy())
.filter(header("JmsIntegration"))
.inOut("jms:someQueue"))
.end()
.end()
.to(...);
您仍然需要实施
MyStrategy
来组合这两条消息。拆分器会自动将拆分的交换重新聚合在一起。但是,默认(自2.3版起)聚合策略是返回原始exchange。通过直接在拆分器上指定默认策略,可以轻松地用自己的策略覆盖默认策略。此外,如果您没有可供选择的流,那么使用过滤器就容易得多。例如:
from("direct:abc")
.split().method(MySplitter.class, "split").aggregationStrategy(new MyStrategy())
.filter(header("JmsIntegration"))
.inOut("jms:someQueue"))
.end()
.end()
.to(...);
您仍然需要实施
MyStrategy
来组合这两条消息。您说过您考虑使用Enricher,但不想发送原始消息。您可以通过使用预JMS路由巧妙地解决此问题:
from("direct:abc")
.enrich("direct:sendToJms", new MyAggregation());
.to("direct:continue");
from("direct:sendToJms")
// do marshalling or conversion here as necessary
.convertBodyTo(MyJmsRequest.class)
.to("jms:someQueue");
public class MyAggregation implements AggregationStrategy {
public Exchange aggregate(Exchange original, Exchange resource) {
MyBody originalBody = original.getIn().getBody(MyBody.class);
MyJmsResponse resourceResponse = resource.getIn().getBody(MyJmsResponse.class);
Object mergeResult = ... // combine original body and resource response
original.getIn().setBody(mergeResult);
return original;
}
}
你说你考虑使用Enricher,但你不想发送原始信息。您可以通过使用预JMS路由巧妙地解决此问题:
from("direct:abc")
.enrich("direct:sendToJms", new MyAggregation());
.to("direct:continue");
from("direct:sendToJms")
// do marshalling or conversion here as necessary
.convertBodyTo(MyJmsRequest.class)
.to("jms:someQueue");
public class MyAggregation implements AggregationStrategy {
public Exchange aggregate(Exchange original, Exchange resource) {
MyBody originalBody = original.getIn().getBody(MyBody.class);
MyJmsResponse resourceResponse = resource.getIn().getBody(MyJmsResponse.class);
Object mergeResult = ... // combine original body and resource response
original.getIn().setBody(mergeResult);
return original;
}
}
我不明白这是如何解决我的问题的,在一些JMS集成之后,将第一个拆分的消息与第二个完全没有处理的拆分消息放在一起。在您的示例中,moth split消息由同一个MyOrderService bean处理,这与我的完全不同case@Julian,为了更清晰,我已经更新了示例,以使用您的原始代码。此外,我还添加了使用过滤器的建议,这可能是您正在寻找的主要内容