简体   繁体   English

为什么在默认的 Spring Cloud Stream 配置中更改了 Spring Integration 消息方法处理行为

[英]Why Spring Integration message method handling behavoiur is changed in default Spring Cloud Stream configuration

I have an application where Spring Integration (5.1.6 latest) is already used.我有一个已经使用 Spring Integration(最新 5.1.6)的应用程序。 And something like the following flow configured:并且配置了类似于以下流程的内容:

@Configuration
public class SomeConfigClass {
...
    @MessagingGateway(name = "someGateway")
    interface Gateway {
        @Gateway(requestChannel = "inboundChannel")
        @Payload("T(java.time.ZonedDateTime).now()")
        void replicate();
    }

    @Bean
    public DirectChannel inboundChannel() {
        return MessageChannels.direct().get();
    }

    @Bean
    public IntegrationFlow someFlow() {
        return IntegrationFlows.from(inboundChannel())
                .handle(someHandler())
                .channel(OUT)
                .get();
    }

    @Bean
    public SomeHandler someHandler() {
        return new SomeHandler();
    }
}

and

public class SomeHandler implements GenericHandler<Object> {
    @Override
    public Message<List<String>> handle(final Object payload, 
                                        final MessageHeaders headers) {
        ...
        return MessageBuilder
                .withPayload(someList)
                .copyHeaders(headers)
                .setHeader("custom", customHeader)
                .build();
    }
}

Everything works fine.一切正常。

And if I try to find integrationArgumentResolverMessageConverter bean in context initialised I see next converters:如果我尝试在初始化的上下文中找到integrationArgumentResolverMessageConverter bean,我会看到下一个转换器:

  • MappingJackson2MessageConverter
  • ByteArrayMessageConverter
  • ObjectStringMessageConverter
  • GenericMessageConverter

After that I add to my pom dependencies Spring Cloud Stream 2.1.2 dependency and Kinesis Binder 1.2.0.之后,我将 Spring Cloud Stream 2.1.2 依赖项和 Kinesis Binder 1.2.0 添加到我的 pom 依赖项中。 Configure bindings by default.默认配置绑定。

The application starts up but when I trying to process my existing flow it failed with something like:应用程序启动,但是当我尝试处理现有流程时,它失败了,如下所示:

EL1004E: Method call: Method handle(java.time.ZonedDateTime,org.springframework.messaging.MessageHeaders) cannot be found on type packageSomeHandler at org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:225) at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:134) at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:54) at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:390) at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90) at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114) at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:365) at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:172) at org.springfra EL1004E:方法调用:在 org.springframework.expression.spel.ast.MethodReference.findAccessorForMethod(MethodReference.java:225) 的类型 packageSomeHandler 上找不到方法句柄(java.time.ZonedDateTime,org.springframework.messaging.MessageHeaders) org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:134) 在 org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:54) 在 org.springframework.expression.spel .ast.MethodReference$MethodValueRef.getValue(MethodReference.java:390) 在 org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90) 在 org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue (SpelNodeImpl.java:114) at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:365) at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:172) at org.斯普林弗拉mework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:160) at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.invokeExpression(MessagingMethodInvokerHelper.java:664) at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.invokeHandlerMethod(MessagingMethodInvokerHelper.java:655) at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:491) at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:362) at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:106) at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:93) at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal mework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:160) 在 org.springframework.integration.handler.support.MessagingMethodInvokerHelper.invokeExpression(MessagingMethodInvokerHelper.java:664) 在 org.springHelpframework. invokeHandlerMethod(MessagingMethodInvokerHelper.java:655) 在 org.springframework.integration.handler.support.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:491) 在 org.springframework.integration.handler.support.MessagingMethodInvokersHelper.在 org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:106) 在 org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:93) 在 org.springframework.integration.handler.AbstractReplyProducingInMessage.Message (AbstractReplyProducingMessageHandler.java:123) at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:169) at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115) 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:453) at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:401) at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187) at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMes (AbstractReplyProducingMessageHandler.java:123) at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:169) at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.javaorg:115) at在 org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:105) 在 org.springframework.integration.channel.AbstractChannelSubscribable(scribables) 73) 在 org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:453) 在 org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:401) 在 org.springframework.messaging.core.GenericMessagingTemplate .doSend(GenericMessagingTemplate.java:187) 在 org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMes sagingTemplate.java:166) at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47) at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109) at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:151) at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:143) at org.springframework.integration.gateway.MessagingGatewaySupport.send(MessagingGatewaySupport.java:413) at org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:533) at org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:473) at org.springframework.integration.gateway.GatewayProxyFactoryBean.invoke(GatewayProxyFactoryBean.java:463) at org.springframework.aop.framework.ReflectiveMethodInvocati sagingTemplate.java:166) at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47) at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109) at org.springframework.messagingTemplate.java:109) .core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:151) 在 org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:143) 在 org.springframework.integration.gateway.Support.Messaging4Gateway.Support.javassaging(Gateway) ) 在 org.springframework.integration.gateway.GatewayProxyFactoryBean.invokeGatewayMethod(GatewayProxyFactoryBean.java:533) 在 org.springframework.integration.gateway.GatewayProxyFactoryBean.doInvoke(GatewayProxyFactoryBean.java:473) 在 org.springframework.integration.gateway.gateway.在 org.springframework.aop.framework.ReflectiveMethodInvocati 调用(GatewayProxyFactoryBean.java:463) on.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy444.replicate(Unknown Source) on.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy444.replicate(Unknown Source)

And when I try to get the same integrationArgumentResolverMessageConverter bean from initialized context I see next chain:当我尝试从初始化的上下文中获取相同的integrationArgumentResolverMessageConverter bean 时,我看到下一个链:

  • ApplicationJsonMessageMarshallingConverter
  • TupleJsonMessageConverter
  • ByteArrayMessageConverter
  • ObjectStringMessageConverter
  • JavaSerializationMessageConverter
  • KryoMessageConverter
  • JsonUnmarshallingConverter

And there is no GenericMessageConverter .并且没有GenericMessageConverter As I understand it cannot be converted because of this converter missed (correct me please if I am wrong).据我所知,由于错过了这个转换器,它无法转换(如果我错了,请纠正我)。

Why is the behaviour different when I just add Spring Cloud Stream default configuration?为什么当我只添加 Spring Cloud Stream 默认配置时行为不同? Or how to customize of using converters chain for specific flow?或者如何自定义使用特定流程的转换器链? Or how to keep message conversation behaviour for different integration flow?或者如何保持不同集成流程的消息对话行为?


Update: So as I investigated spring cloud stream re-defines not only default integration MessageConverter s, but also it re-defines default HandlerMethodArgumentResolver s, which is used to map method argument with a message..更新:因此,当我调查 spring cloud stream 时,不仅重新定义了默认集成MessageConverter s,而且还重新定义了默认HandlerMethodArgumentResolver s,它用于将方法参数与消息映射..

Before additing Spring Cloud Stream:添加 Spring Cloud Stream 之前:

  • HeaderMethodArgumentResolver
  • HeadersMethodArgumentResolver
  • MessageMethodArgumentResolver
  • PayloadExpressionArgumentResolver
  • NullAwarePayloadArgumentResolver
  • PayloadsArgumentResolver
  • MapArgumentResolver
  • PayloadArgumentResolver

After additing Spring Cloud Stream:添加 Spring Cloud Stream 后:

  • SmartPayloadArgumentResolver
  • SmartMessageMethodArgumentResolver
  • HeaderMethodArgumentResolver
  • HeadersMethodArgumentResolver
  • PayloadExpressionArgumentResolver
  • NullAwarePayloadArgumentResolver
  • PayloadExpressionArgumentResolver
  • PayloadsArgumentResolver
  • MapArgumentResolver

There two deprecated SmartPayloadArgumentResolver and SmartMessageMethodArgumentResolver with fix for conversion from byte[] payload to Object .有两个已弃用的SmartPayloadArgumentResolverSmartMessageMethodArgumentResolver修复了从byte[]负载到Object转换。 But what I cannot understand why there are two PayloadExpressionArgumentResolver ?..但是我不明白为什么有两个PayloadExpressionArgumentResolver ?..

And the main question: why Spring Cloud Stream default application context affects Spring Integration default application context, I thought before that Stream's resolvers/converters were only related to message endpoints linked with stream destination channels...主要问题是:为什么 Spring Cloud Stream 默认应用程序上下文会影响 Spring Integration 默认应用程序上下文,我之前认为 Stream 的解析器/转换器仅与与流目标通道链接的消息端点有关...

我不知道为什么 Stream 会丢弃那个转换器(可能是一个错误,也许在那里打开一个 GitHub 问题),但我相信你可以将它作为@StreamMessageConverter @Bean添加回来,如流文档中所讨论的那样。

After investigation I can make assumption that the behaviour of method message handling is changed because ofSpring Cloud Stream 's issue and corresponding Spring Framework 's issue .经过调查,我可以假设由于Spring Cloud Stream的问题和相应的Spring Framework的问题,方法消息处理的行为发生了变化。 There is temporary overriden argument resolvers initialization in Spring Binder auto-configuration (bean definition on static method BinderFactoryConfiguration#messageHandlerMethodFactory ). Spring Binder 自动配置中有临时覆盖参数解析器初始化(静态方法BinderFactoryConfiguration#messageHandlerMethodFactory上的 bean 定义)。

So first resolver in chain is SmartPayloadArgumentResolver which decides that the conversation is needed.所以链中的第一个解析器是SmartPayloadArgumentResolver ,它决定需要对话。 This conversation is started and failed by ApplicationJsonMessageMarshallingConverter .此对话由ApplicationJsonMessageMarshallingConverter启动和失败。 The exception:例外:

org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Unexpected character ('-' (code 45)): Expected space separating root-level values
 at [Source: (String)"2019-09-04T01:26:20.202Z[UTC]"; line: 1, column: 6]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unexpected character ('-' (code 45)): Expected space separating root-level values
 at [Source: (String)"2019-09-04T01:26:20.202Z[UTC]"; line: 1, column: 6], failedMessage=GenericMessage [payload=2019-09-04T01:26:20.202Z[UTC], headers={spanTraceId=3f87b9afc373308a, spanId=3f87b9afc373308a, nativeHeaders={spanTraceId=[3f87b9afc373308a], spanId=[3f87b9afc373308a], spanSampled=[1]}, X-B3-SpanId=3f87b9afc373308a, X-B3-Sampled=1, X-B3-TraceId=3f87b9afc373308a, id=3fbe87e3-31c4-4d21-c3fb-506c018c0e25, spanSampled=1, timestamp=1567560380202}]

And as result I face error aforementioned in the question thrown from MethodReference .结果我在MethodReference抛出的问题中遇到了前面提到的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM