Java 从直接通道流返回值并在Spring集成中继续异步流

Java 从直接通道流返回值并在Spring集成中继续异步流,java,spring,spring-integration,Java,Spring,Spring Integration,我的web应用中有以下集成配置: @Bean IntegrationFlow giraFlow() { return IntegrationFlows.from( MessageChannels.direct("gira.input")) .split() .transform(transformer) .handle(parserService) .channel(r

我的web应用中有以下集成配置:

@Bean
IntegrationFlow giraFlow() {
    return IntegrationFlows.from(
            MessageChannels.direct("gira.input"))
            .split()
            .transform(transformer)
            .handle(parserService)
            .channel(routerChannel())
            .get();
}

@Bean
MessageChannel routerChannel() {
    return MessageChannels.queue("routerChannel", 10)
            .get();
}


@Bean
IntegrationFlow routerChannelFlow() {
    return IntegrationFlows.from(
            routerChannel())
            .route(p -> p.getKind().name(),
                    m -> m.suffix("Channel")
                            .channelMapping(TaskKind.CREATE.name(), "create")
                            .channelMapping(TaskKind.RELOAD.name(), "reload")
            .get();
}
和网关:

@MessagingGateway
public interface GW {

    @Gateway(requestChannel = "gira.input")
    Task gira(Collection<Request> messages);

}
我从SpringMVC控制器调用gateway方法,希望它返回一个
Task
对象,
parserService
在其body方法中返回该对象。重要的是,我希望阻止控制器,直到它从
parserService
获取值。在它获得这个值之后,我希望我的集成流与
routerChannelFlow
异步进行,这样web控制器方法将尽快返回,并且
routerChannelFlow
中的所有繁重操作都将在不阻塞控制器的情况下完成

以下是具有此网关方法调用的控制器的一部分:

...
Task gira = gw.gira(messages);
log.info("Result {}", gira);
...
问题是,
log.info
永远无法访问,而
gira()
网关永远被阻止

我怎样才能达到我想要的行为

另外,
parserService
在我的应用程序中实际上是不需要的,这正是我认为可以帮助我定义网关返回值的,但实际上没有帮助:(

更新

下面是我在Gary Russell的评论后得到的:

@Bean
public ThreadPoolTaskExecutor executor() {
    ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
    pool.setCorePoolSize(10);
    pool.setMaxPoolSize(10);
    pool.setWaitForTasksToCompleteOnShutdown(true);
    return pool;
}

@Bean
MessageChannel routerChannel() {
    return MessageChannels
            .publishSubscribe("routerChannel", executor())
            .get();
}

@Bean
IntegrationFlow routerChannelFlow() {
    return IntegrationFlows
            .from(routerChannel())
            .publishSubscribeChannel(s -> s
                 .subscribe(f -> f
                         .bridge(null))
                 .subscribe(process()))
            .get();
}

@Bean
IntegrationFlow process() {
    return f ->
            f.<IssueTrackerTask, String>route(p -> p.getKind().name(),
                    m -> m.suffix("Channel")
                            .channelMapping(TaskKind.CREATE.name(), "create")
                            .channelMapping(TaskKind.RELOAD.name(), "reload")

}
@Bean
公共线程池TaskExecutor executor(){
ThreadPoolTaskExecutor池=新的ThreadPoolTaskExecutor();
池。setCorePoolSize(10);
pool.setMaxPoolSize(10);
设置waitfortaskstocompletionshutdown(true);
回流池;
}
@豆子
MessageChannel路由通道(){
返回消息通道
.publishSubscribe(“路由通道”,executor())
.get();
}
@豆子
集成流路由通道流(){
返回积分流
.from(路由通道())
.publishSubscribeChannel(s->s)
.订阅(f->f
.bridge(空))
.subscribe(进程())
.get();
}
@豆子
集成流程(){
返回f->
f、 路由(p->p.getKind().name(),
m->m.后缀(“通道”)
.channelMapping(TaskKind.CREATE.name(),“CREATE”)
.channelMapping(TaskKind.RELOAD.name(),“RELOAD”)
}
当我尝试使用此管道时,我得到以下错误
Dispatcher没有频道'application:development:9000.dummy'的订户。
。这肯定是一个配置错误的问题,但我无法找出我做错了什么

更新


频道(“虚拟”)
更改为
桥接(空)

创建
重新加载
频道的下游是什么

您如何处理控制器中的
任务
结果(除了记录它)

如果不需要结果,请将网关返回更改为void,并在网关下游添加执行器通道

如果希望返回
任务
对象,则需要将
路由通道
作为一个发布/订阅通道,包含一个执行器和两个订阅者-一个无处可去的桥接器(输入通道和无输出通道)它将
任务
返回到网关,路由器将在单独的线程上路由任务;来自路由器的下游流不得返回结果(网关在等待结果之前很久就会停止)


您可以将两个路由器通道改为执行器通道,而不是向
路由器通道添加执行器。

您的上一个解决方案就快到了,您不需要使用
.channel(“dummy”)
,只需在
.publishSubscribeChannel()的第一个子流订阅服务器中使用
.bridge(null)

您需要的只是将消息发送回网关的
replyChannel
,它是消息头中的
临时replyChannel

BridgeHandler
是“不做任何事情”的最佳方式,只需将消息从标题发送到相应的
replyChannel


还考虑在<代码> > StUTE()/<代码>之后添加“<代码>执行器< /代码>”,如果您的代码> >()/代码>和<代码>

逻辑足够重。

谢谢你的回复。我用我得到的更新了答案,仍然在努力获得正确的配置。还有一个问题仍然存在:你建议在
split()之后添加另一个
executor
,但它将解决什么问题?控制器在从网关获得答案之前仍然被阻止,因此它将以任何方式被阻止。使用
executor
有什么好处吗?拆分后的项目将被并行处理。没有-一个接一个。Artem,太棒了,明白了,谢谢。你和Russel正在做一个版本我在StackOverflow做得很好,回答了我有关集成的问题。再次感谢!
@Bean
public ThreadPoolTaskExecutor executor() {
    ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
    pool.setCorePoolSize(10);
    pool.setMaxPoolSize(10);
    pool.setWaitForTasksToCompleteOnShutdown(true);
    return pool;
}

@Bean
MessageChannel routerChannel() {
    return MessageChannels
            .publishSubscribe("routerChannel", executor())
            .get();
}

@Bean
IntegrationFlow routerChannelFlow() {
    return IntegrationFlows
            .from(routerChannel())
            .publishSubscribeChannel(s -> s
                 .subscribe(f -> f
                         .bridge(null))
                 .subscribe(process()))
            .get();
}

@Bean
IntegrationFlow process() {
    return f ->
            f.<IssueTrackerTask, String>route(p -> p.getKind().name(),
                    m -> m.suffix("Channel")
                            .channelMapping(TaskKind.CREATE.name(), "create")
                            .channelMapping(TaskKind.RELOAD.name(), "reload")

}