Spring Integration 5.2.2.RELEASE - 使用@IntegrationConverter 的集成流转换不适用于 jackson 数据绑定

Spring Integration 5.2.2.RELEASE - integration flow convertion with @IntegrationConverter doesn't work with jackson databind

我将 Spring 引导版本从 2.1.8.RELEASE 升级到 2.2.2.RELEASE(因此 Spring 集成从 5.15.2.2.RELEASE)并且如果我们在符合条件的 spring 转换器中有一个 jackson 转换器,那么使用 @IntegrationConverter 的自动转换似乎不再有效。

转换器是自动声明的,因为我在我的项目依赖项中声明了对 jackson-databind 的依赖项。我需要 jackson,因为我必须将从 HTTP 请求接收到的有效负载转换为 java bean。但是因为声明了这个转换器,所以使用它而不是 Spring 集成 GenericMessageConverter 并且它无法转换,因为它首先尝试在 bean 上调用 toString() 然后转换 toString() 对象表示。

我在 github 的主机中有一个样本:https://github.com/Kruschenstein/spring-integration-playground。这是一个简单的 Spring 集成流程,其中我们 运行 一个服务器,根据用户输入请求 HTTP API。典型的应用程序用法是 运行 宁 telnet localhost 1234 输入一个介于 0255 之间的数字,关于猫的事实将显示在用户终端中。

这是我从 telnet 客户端发送请求时得到的错误日志:

org.springframework.integration.transformer.MessageTransformationException: Failed to transform Message in bean 'server.transformer#2' for component 'server.org.springframework.integration.config.ConsumerEndpointFactoryBean#5'; defined in: 'org.grorg.integration.IntegrationApplication'; from source: 'bean method server'; nested exception is org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Unrecognized token 'org': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (String)"org.grorg.integration.model.api.Fact@22fae1e0"; line: 1, column: 4]; nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'org': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
 at [Source: (String)"org.grorg.integration.model.api.Fact@22fae1e0"; line: 1, column: 4], failedMessage=GenericMessage [payload=org.grorg.integration.model.api.Fact@22fae1e0, headers={errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@cdb23ed, Server=Cowboy, ip_tcp_remotePort=54966, NUM=1, Connection=keep-alive, ip_localInetAddress=/127.0.0.1, ip_address=127.0.0.1, http_statusCode=200 OK, Date=1578329608000, Via=1.1 vegur, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@cdb23ed, Etag=W/"10db9-+ezvkUu4LsJ+zW4+jWiIrVy9v5E", ip_connectionId=localhost:54966:1234:2a75cd25-8e85-4b49-a124-4db58aac3b84, Set-Cookie=connect.sid=s%3A8-aFqwlU8601G1vSPXCnc4Wskla8GzpS.JBIKqFX1%2Fw%2BU7py1QOKqI2G1%2FdJNeUPBxGdGtbXQGIw; Path=/; HttpOnly, id=83b6790f-27f0-6045-3e0e-8b852ca10b46, Content-Length=69049, contentType=application/json;charset=utf-8, ip_hostname=localhost, timestamp=1578329608525}]

前两个提交是工作方法。第一次提交有效,因为 à force GenericMessageConverter 被使用。第二次提交只是表明它可以与 Spring 集成 5.0.

一起正常工作

这是一个解决方法:

    @Bean(name = IntegrationContextUtils.ARGUMENT_RESOLVER_MESSAGE_CONVERTER_BEAN_NAME)
    public static ConfigurableCompositeMessageConverter configurableCompositeMessageConverter(
            @Qualifier(IntegrationUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME) ConversionService conversionService) {
        return new ConfigurableCompositeMessageConverter(
                Collections.singleton(new GenericMessageConverter(conversionService)));
    }

我是否错误地使用了集成流程的类型转换?您有新版本的铸造对象的新解决方案吗?或者这只是一种倒退?

提前致谢!

因此,问题确实在于 MappingJackson2MessageConverter 试图将 Fact 实例转换为 CatFact。这发生在 Http.outboundGateway() 之后 - 响应带有 contentType header 作为 application/json。这确实是一个提示 MappingJackson2MessageConverter 尝试将一个 object 转换为另一个

当我在你的流程中这样做时:

            .transform(Message.class, m -> {
                Facts facts = (Facts) m.getPayload();
                int num = (int) m.getHeaders().get("NUM");
                return facts.getAll().get(num);
            })
            .headerFilter(MessageHeaders.CONTENT_TYPE)
            .transform(CatFact.class, id -> id)

(注意headerFilter()),返回工作状态GenericMessageConverter

这不是错误或回归。这只是 header 和负载之间的 non-consistent 状态的事实。不过,我们可能需要考虑如何缓解它...请随意提出 GH 问题并提出一些想法。