打破DSL IntegrationFlows

时间:2016-01-10 14:05:21

标签: spring-integration

我一直在使用Spring Integration(SI)DSL。我有一个Rest服务,定义了以下Async Gateway:

@MessagingGateway
public interface Provision {
    @Async
    @Gateway(requestChannel = "provision.input")
    ListenableFuture<List<ResultDto>> provision(List<ItemsDto> stuff);
}

从逐行演练中我有以下示例IntegrationFlow。

@Bean
public IntegrationFlow provision() {
    return f -> f
            .split(ArrayList.class, List::toArray)
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .<ItemsDto, String>route(ItemsDto::getType, m -> m
                            .subFlowMapping("IPTV", sf -> sf
                                            .<ItemsDto, String>route(ItemsDto::getAction, m2 -> m2
                                                    .subFlowMapping("OPEN", sf2 -> sf2
                                                            .handle((p, h) -> iptvService.open((ItemsDto) p))))
                            )
            )
            .aggregate();
}

我可以看到几层路由。我需要稍微分解一下。我尝试了几件不起作用的东西(这里我没有得到回应......线程不等待):

@Bean(name = "routerInput")
private MessageChannel routerInput() {
    return MessageChannels.direct().get();
}

@Bean
public IntegrationFlow provision() {
    return f -> f
            .split(ArrayList.class, List::toArray)
            .channel(c -> c.executor(Executors.newCachedThreadPool()))
            .<ItemsDto, String>route(ItemsDto::getType, m ->
                            m.subFlowMapping("IPTV", sf -> sf.channel("routerInput"))
            )
            .aggregate();
}

@Bean
public IntegrationFlow action() {
    return IntegrationFlows.from("routerInput")
            .<ItemsDto, String>route(ItemsDto::getAction, m -> m
                    .subFlowMapping("OPEN", sf -> sf
                            .handle(p -> iptvService.open((ItemsDto) p.getPayload())))).get();
}

我显然在概念上遗漏了一些东西:)有人可能会帮助提供“如何和为什么”的观点?

我有一个需要拆分的项目列表,按“类型”路由,然后通过“操作”路由,最后聚合(包含处理程序的响应)。每个处理的项目都需要并行处理。

提前致谢

更新: 从Artem的建议我删除了所有异步的东西。我把它修剪得几乎没有......

@Bean(name = "routerInput")
private MessageChannel routerInput() {
    return MessageChannels.direct().get();
}

@Bean
public IntegrationFlow provision() {
    return f -> f
            .split()
            .<ItemDto, String>route(ItemDto::getType, m ->
                    m.subFlowMapping("IPTV", sf -> sf.channel("routerInput")))
            .aggregate();
}

@Bean
public IntegrationFlow action() {
    return IntegrationFlows.from("routerInput")
            .<ItemDto, String>route(ItemDto::getAction, m -> m
                    .subFlowMapping("OPEN", sf -> sf
                            .handle((p, h) -> iptvService.open((ItemDto) p)))).get();
}

我通过更改

来做出回应

.handle(p - &gt;

到这个

.handle((p,h) - &gt;

所以它至少会响应,但它不会聚合分裂的3个测试项目。输出包含1个项目。我需要使用流收集吗?发布政策?这不应该没问题吗?

3 个答案:

答案 0 :(得分:0)

如果你想将它分开,使用def create_hist(a,dr): class SaveArraysCallable(object): def __call__(self,bins,hist): self.bins = bins.copy() self.hist = hist.copy() f = SaveArrayCallable() fortran_module.create_hist(a,dr,f) return f.bins, f.hist 而不是channelMapping可能更简单......

subflowMapping

为其他选项创建流并聚合每个结果:

    @Bean
    public IntegrationFlow typeRoute() {
        return IntegrationFlows.from(foo())
                .split()
                .<ItemsDto, String>route(ItemsDto::getType, m -> m
                        .channelMapping("foo", "channel1")
                        .channelMapping("bar", "channel2"))
                .get();
    }

    @Bean
    public IntegrationFlow fooActionRoute() {
        return IntegrationFlows.from(channel1())
                .<ItemsDto, String>route(ItemsDto::getAction, m -> m
                        .channelMapping("foo", "channel3")
                        .channelMapping("bar", "channel4"))
                .get();
    }

    @Bean
    public IntegrationFlow barActionRoute() {
        return IntegrationFlows.from(channel1())
                .<ItemsDto, String>route(ItemsDto::getAction, m -> m
                        .channelMapping("foo", "channel5")
                        .channelMapping("bar", "channel6"))
                .get();
    }

    @Bean
    public IntegrationFlow fooFooHandle() {
        return IntegrationFlows.from(channel3())
                // handle
                .channel(aggChannel())
                .get();
    }

使用 // fooBarHandle(), barFooHandle(), barBarHandle() @Bean IntegrationFlow agg() { return IntegrationFlows.from(aggChannel()) .aggregate() .get(); } s ...

处理并行性
ExecutorChannel

答案 1 :(得分:0)

我没有看到您的配置中存在任何重大问题,而且确实应该有效。

希望我不喜欢有:

  1. 如果您使用async网关(ListenableFuture<List<ResultDto>>),则不需要@Async注释,因为它已经是网关合同。

  2. 如果List::toArray已经是payload,则您不需要转换List。只使用没有参数的.split()就足够了。

  3. 这就是设计风格。

    我还不确定那里的问题是什么,但你是否想让你的整个流程同步并在这里与我们分享DEBUG流动并指出你看到问题的地方。

答案 2 :(得分:0)

将聚合移动到“action”Bean并且它有效。 感谢您的耐心:)