Java 从直接通道流返回值并在Spring集成中继续异步流
我的web应用中有以下集成配置: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
@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")
}