由于单向MessageHandler,spring-integration并行split-route-aggregate流失败

时间:2018-05-01 17:58:09

标签: spring-integration spring-integration-dsl

我希望通过拆分它们来并行处理项目列表,将每个项目路由到适当的网关并聚合结果。但是,我的应用程序无法启动,我收到以下错误:

BeanCreationException: The 'currentComponent' ... is a one-way 'MessageHandler' 
and it isn't appropriate to configure 'outputChannel'. 
This is the end of the integration flow.

这是一个示例流程定义,用于说明行为:

@Bean
public IntegrationFlow parallelSplitRouteAggregateFlow() {
    return IntegrationFlows
            .from(Http.inboundGateway("/trigger"))
            .handle(message -> Arrays.asList(1, 2, 3))
            .split()
            .channel(MessageChannels.executor(Executors.newCachedThreadPool()))
            .<Integer, Boolean>route(o -> o % 2 == 0, m -> m
                    .subFlowMapping(true, oddFlow())
                    .subFlowMapping(false, evenFlow()))
            .aggregate()
            .get();
}

@Bean
public IntegrationFlow oddFlow() {
    return flow -> flow.<Integer>handle((payload, headers) -> "odd");
}

@Bean
public IntegrationFlow evenFlow() {
    return flow -> flow.<Integer>handle((payload, headers) -> "even");
}

我见过Error 'is a one-way 'MessageHandler' for spring-integration aggregator DSL,但这里的解决方案不适用,我没有登录handle()方法。 我还尝试将.defaultOutputToParentFlow()添加到mappingDefinition,因为cafe示例使用它,但这也没有区别。

我应该提一下,这是Spring-integration 5.0.4 with spring-boot 2.0.1 release。

3 个答案:

答案 0 :(得分:3)

你的问题在这里:

runas

如果您使用内联实现,它将如下所示:

.handle(message -> Arrays.asList(1, 2, 3))

注意.handle(new MessageHandler() { @Override public void handleMessage(Message<?> message) throws MessagingException { Arrays.asList(1, 2, 3); } }) 返回类型。由于没有任何东西可以返回,因此无需向下游发送任何内容 - void

要解决您的问题,您需要这样做:

is a one-way 'MessageHandler'

相当于:

 .handle((p, h) -> Arrays.asList(1, 2, 3))

实际上我的IDEA为我的变体说:

enter image description here

这让我有一些暗示,我做错了什么。

<强>更新

工作代码:

.handle(new GenericHandler<Object>() {

        @Override
        public Object handle(Object p, Map<String, Object> h) {
            return Arrays.asList(1, 2, 3);
        }
})

答案 1 :(得分:2)

@Bean
public IntegrationFlow parallelSplitRouteAggregateFlow() {
    return IntegrationFlows
            .from(Http.inboundGateway("/trigger"))
            .handle((p, h) -> Arrays.asList(1, 2, 3))
            .split()
            .channel(MessageChannels.executor(Executors.newCachedThreadPool()))
            .<Integer, Boolean>route(o -> o % 2 == 0, m -> m
                    .subFlowMapping(true, oddFlow())
                    .subFlowMapping(false, evenFlow()))
            .get();
}

@Bean
public IntegrationFlow oddFlow() {
    return flow -> flow.<Integer>handle((payload, headers) -> "odd")
            .channel("agg.input");
}

@Bean
public IntegrationFlow evenFlow() {
    return flow -> flow.<Integer>handle((payload, headers) -> "even")
        .channel("agg.input");
}

@Bean
public IntegrationFlow agg() {
    return f -> f.aggregate();
}

enter image description here

答案 2 :(得分:0)

如果您需要在多个“工作人员”上“分发”消息,并将消息返回到连接点,则可以使用方法.scatterGather(...)。看来,它以更适合在IntegrationFlow的域内使用的方式包装了.route(...)功能。

在以下示例中显示:

    @Bean
    public IntegrationFlow evenOddFlows() {
        return IntegrationFlows.from(Http.inboundGateway("/trigger"))
                .handle((payload,headers)->Arrays.asList(1,2,3))
                .split()
                .scatterGather(r->r.applySequence(true)
                .recipientFlow(m->(int)m.getPayload()%2==0, evenFlow-> evenFlow.log(m->"Even flow with payload: "+m.getPayload()).<Integer,Integer>transform(h-> h+50)
                        .handle((payload,headers)->(int)payload+50).log(m->"At Even flow end with payload: "+m.getPayload())
                        .handle((payload,headers)->payload) /* This .handle(...) doesn't do a real job.
* Instead, it is to patch something that at least I regard as a bug.
* Having not the .handle(...) would leave the .log(...) at the end of the flow.
* After crossing a .log(...) if right at the flow's end, the response message doesn't arrive back the parent flow (hence my aprising there is a bug).
* With the "appended" .handle(...) afterwards, avoid the .log(...) being the last one in the flow, as well as tests show the message is sent away where the parent flow receives it.
*/
                        )
                        .recipientFlow(m->(int)m.getPayload()%2!=0, oddFlow-> oddFlow.log(m->"Odd flow with payload: "+m.getPayload()).<Integer,Integer>transform(h-> h+10)
                        .handle((payload,headers)->(int)payload+10).log(m->"At Odd flow end with payload: "+m.getPayload())
                        .handle((payload,headers)->payload) // This .handle(...) I needed as a patch because otherwise the .log(...) being the last one in the subflow swallowed the message
                        )
                        )
                        .aggregate()
                        .get()
                ;
    }
curl -i -H "Content-type: application/json" http://localhost:8080/trigger

卷曲输出:

[[21],[102],[23]]

日志:

2019-05-17 16:19:11.061  INFO 10148 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler   : Odd flow with payload: 1
2019-05-17 16:19:11.061  INFO 10148 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler   : At Odd flow end with payload: 21
2019-05-17 16:19:11.061  INFO 10148 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler   : Even flow with payload: 2
2019-05-17 16:19:11.061  INFO 10148 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler   : At Even flow end with payload: 102
2019-05-17 16:19:11.061  INFO 10148 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler   : Odd flow with payload: 3
2019-05-17 16:19:11.061  INFO 10148 --- [nio-8080-exec-1] o.s.integration.handler.LoggingHandler   : At Odd flow end with payload: 23