在Spring Application Context中找不到已注册的RendezvousChannel Bean

时间:2018-09-04 15:28:32

标签: spring-boot spring-integration

在Spring Boot应用程序中,我们通过利用Spring Integration中的RendezvousChannel来使用请求-响应模式。收到请求后,我们将创建一个唯一命名的通道,并在Spring应用程序上下文中注册它,如下所示:

RendezvousChannel rendezvousChannel = MessageChannels.rendezvous(uniqueId).get();
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) springContext;
SingletonBeanRegistry beanRegistry = configurableApplicationContext.getBeanFactory();
beanRegistry.registerSingleton(uniqueId, rendezvousChannel);

然后,我们将此频道名称添加到请求中,并执行需要花费几秒钟的工作。然后,对该请求的响应到达并被路由到RendezvousChannel

@Bean
public IntegrationFlow flow() {
    return IntegrationFlows.from(globalChannel)
            .route("payload['replyChannel']")
            .get();
}

这很好用,我们会根据需要收到对请求的响应。 但是在负载下,当温度很高时。 RendezvousChannels已创建,路由有时会失败,并显示以下信息:

org.springframework.messaging.MessagingException: failed to resolve channel name 'uniqueId'; 
nested exception is org.springframework.messaging.core.DestinationResolutionException: failed to look up MessageChannel with name 'uniqueId' in the BeanFactory.; 
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'uniqueId' available, failedMessage=GenericMessage...
at org.springframework.integration.router.AbstractMappingMessageRouter.resolveChannelForName(AbstractMappingMessageRouter.java:227)
at org.springframework.integration.router.AbstractMappingMessageRouter.addChannelFromString(AbstractMappingMessageRouter.java:258)
at org.springframework.integration.router.AbstractMappingMessageRouter.addToCollection(AbstractMappingMessageRouter.java:282)
at org.springframework.integration.router.AbstractMappingMessageRouter.determineTargetChannels(AbstractMappingMessageRouter.java:186)
at org.springframework.integration.router.AbstractMessageRouter.handleMessageInternal(AbstractMessageRouter.java:171)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:158)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:132)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:105)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:73)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:445)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:394)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:181)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:160)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:426)

目前我不确定为什么会这样。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

对于请求答复的情况,我们建议使用@MessagingGatewayhttps://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints-chapter.html#gateway

此代码将TemporaryReplyChannel实例填充到replyChannel键下的标头中。在发送到某些外部出站服务之前,您需要在IntegrationFlow中使用以下内容:

.enrichHeaders(h -> h.headerChannelsToString())

通过这种方式,将提到的TemporaryReplyChannel存储在某些特定的HeaderChannelRegistry中:https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-transformation-chapter.html#header-channel-registry

之后,您确实可以根据需要提供一些transform()来将replyHeader打包到有效负载中。为此,我们提供了EmbeddedJsonHeadersMessageMapper之类的东西,可以从提到的transform()中将其用作普通的POJO使用者。

收到回复时,应确保至少包含必需的replyChannel属性和实际的回复有效内容。在这种情况下,您可以再次使用EmbeddedJsonHeadersMessageMapper.toMessage()将嵌入的标头重新映射回MessageHeaders,或者您需要确保自己进行重新映射。在这种情况下,必须填充replyChannel标头很重要。最后,您只需要对标准机制进行答复即可从标头将输出发送到replyChannel。上面提到的HeaderChannelRegistry将确保将字符串ID解析为实际的TemporaryReplyChannel实例,同时开头的网关仍将等待该TemporaryReplyChannel的值。