英文:
Spring integration routing with multiple rules
问题
我正在使用基于DSL的Spring Integration,并且我需要将消息路由到不同的通道。简而言之,在发生失败的情况下,它们应该进入一个输出通道;在成功的情况下,它们应该进入两个通道中的一个。这两种路由都基于头部参数。
我创建了两个路由器。一个用于处理失败,另一个用于处理成功。但是当我尝试启动应用程序时,我收到以下错误消息:
nested exception is org.springframework.beans.factory.BeanCreationException: The 'currentComponent' (org.springframework.integration.router.MethodInvokingRouter@50ac1249) is a one-way 'MessageHandler' and it isn't appropriate to configure 'failure-channel'. This is the end of the integration flow.
我的流程定义如下:
@Bean
public IntegrationFlow myFlow() {
return IntegrationFlows.from("from")
.route(Message.class,
message -> message
.getHeaders().containsKey("FAILURE"),
mapping -> mapping
.channelMapping(true, "failure-channel"))
.route(Message.class,
message -> message
.getHeaders().get("NEXT"),
mapping -> mapping
.channelMapping("first", "first-channel")
.channelMapping("second", "second-channel"))
.get();
}
如何实现这个逻辑呢?根据我在文档中的阅读,定义多个路由是没有问题的。两个条件在独立情况下都是有效的,因为为了使其工作,我创建了另一个通道来接收成功消息,并且只执行第二个路由。
我猜测问题是因为第一个路由器消耗了消息,但是我正在寻找类似于“如果路由A没有解析,则转到路由B”的行为。
<details>
<summary>英文:</summary>
I'm using Spring Integration with DSL and I need to route messages for various channels. Simply put, in case of failure they should go to an output channel, in case of success they should go to one of two channels. Both routings are based on header parameters.
I created two routers. One to handle failures and another to handle successes, but when I try to start the application I get the following error:
nested exception is org.springframework.beans.factory.BeanCreationException: The 'currentComponent' (org.springframework.integration.router.MethodInvokingRouter@50ac1249) is a one-way 'MessageHandler' and it isn't appropriate to configure 'failure-channel'. This is the end of the integration flow.
My flow definition
@Bean
public IntegrationFlow myFlow() {
return IntegrationFlows.from("from")
.route(Message.class,
message -> message
.getHeaders().containsKey("FAILURE"),
mapping -> mapping
.channelMapping(true, "failure-channel"))
.route(Message.class,
message -> message
.getHeaders().get("NEXT"),
mapping -> mapping
.channelMapping("first", "first-channel")
.channelMapping("second", "second-channel")
.get();
}
How can I implement this logic? As far as I read in the documentation, there's no problem in having more than one route defined and both conditions are valid in isolation, since to have it working I created another channel that receives the successes and only does the second routing.
I'm assuming the problem is because the first router consumes the message, but I was looking for a behaviour similar to *if route A does not resolve go to route B*.
</details>
# 答案1
**得分**: 1
看一下 `RouterSpec`:
/**
* 将路由器的默认输出映射到父流程。
* 使用下一个路由器后的父流程{@link MessageChannel}作为此路由器的{@link AbstractMessageRouter#setDefaultOutputChannel(MessageChannel)}。
* @return 路由器规范。
*/
public S defaultOutputToParentFlow() {
文档中还有一条注释:https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl-routers
> `.routeToRecipients()` 的 `.defaultOutputToParentFlow()` 定义可让您将路由器的`defaultOutput`设置为网关,以继续处理主流程中未匹配的消息。
因此,没有`FAILURE`头的第一个路由器将其输出发送到主流程,以进行所需的`NEXT`路由器的处理。
<details>
<summary>英文:</summary>
See `RouterSpec`:
/**
* Make a default output mapping of the router to the parent flow.
* Use the next, after router, parent flow {@link MessageChannel} as a
* {@link AbstractMessageRouter#setDefaultOutputChannel(MessageChannel)} of this router.
* @return the router spec.
*/
public S defaultOutputToParentFlow() {
And there is also a note in the docs: https://docs.spring.io/spring-integration/docs/current/reference/html/dsl.html#java-dsl-routers
> The `.defaultOutputToParentFlow()` of the `.routeToRecipients()` definition lets you set the router’s `defaultOutput` as a gateway to continue a process for the unmatched messages in the main flow.
So, your first router without a `FAILURE` header is going to send its output to the main flow for desired `NEXT` router.
</details>
# 答案2
**得分**: 0
我通过使用`subFlow()`找到了答案。在这种情况下,我最终得到了:
```java
@Bean
public IntegrationFlow myFlow() {
return IntegrationFlows.from("from")
.route(Message.class,
message -> message
.getHeaders().containsKey("FAILURE"),
mapping -> mapping
.channelMapping(true, "failure-channel")
.subFlowMapping(false, sf -> sf.route(Message.class,
message -> message
.getHeaders().get("NEXT"),
subMapping -> subMapping
.channelMapping("first", "first-channel")
.channelMapping("second", "second-channel")
.resolutionRequired(true))
.get();
}
英文:
I found the answer by using a subFlow()
. In this case I ended up with:
@Bean
public IntegrationFlow myFlow() {
return IntegrationFlows.from("from")
.route(Message.class,
message -> message
.getHeaders().containsKey("FAILURE"),
mapping -> mapping
.channelMapping(true, "failure-channel")
.subFlowMapping(false, sf -> sf.route(Message.class,
message -> message
.getHeaders().get("NEXT"),
subMapping -> subMapping
.channelMapping("first", "first-channel")
.channelMapping("second", "second-channel")
.resolutionRequired(true))
.get();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论