Skip to content

Spring Integration 5.1 - integration flow convertion with @IntegrationConverter doesn't work #3052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Kruschenstein opened this issue Sep 13, 2019 · 0 comments · Fixed by #3053
Assignees
Milestone

Comments

@Kruschenstein
Copy link

Affects Version(s): <5.1>

Bug report

There is a regression from spring integration 5.0 to 5.1. Automatic casting with the instruction .transform(Type.class, id -> id) (or in Spring Integration 5.1 .convert(Type.class)) within a IntegrationFlow doesn't work anymore for version 5.1.

Following, I retype the SO issue (https://stackoverflow.com/questions/57910790/spring-integration-5-1-integration-flow-convertion-with-integrationconverter):

I upgrade my Spring boot version from 2.0.5.RELEASE to 2.1.8.RELEASE (so Spring Integration from 5.0 to 5.1) and the automatic type casting inside integration flow doesn't work anymore. I am used to define a set of @IntegrationConverter components and automatic casting with the operation transform(Type.class, p -> p) inside integration flow code but with the new version it seems to be broken.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.grorg</groupId>
    <artifactId>grointegration</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>grointegration</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-ip</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

And the Main.java file:

package org.grorg.grointegration;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.converter.Converter;
import org.springframework.integration.config.IntegrationConverter;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.Transformers;
import org.springframework.integration.ip.dsl.Tcp;
import org.springframework.stereotype.Component;

class Test {
    @Override
    public String toString() {
        return "test";
    }
}

@Component
@IntegrationConverter
class Convert implements Converter<String, Test> {
    @Override
    public Test convert(String s) {
        return new Test();
    }
}

@SpringBootApplication
public class Main {

    public static void main(String[] args) {
        SpringApplication.run(GrointegrationApplication.class, args);
    }

    @Bean
    public IntegrationFlow server() {
        return IntegrationFlows
                .from(Tcp.inboundGateway(Tcp.netServer(1234)))
                .transform(Transformers.objectToString())
                .transform(Test.class, id -> id) // in 2.1 I could use .convert(Test.class) but the problem is the same
                .log()
                .handle((p, h) -> "OK")
                .get();
    }
}

Use with a shell:

telnet localhost 1234
> test
> OK
[...]

With the previous version (2.0.5.RELEASE) the program work nicely like previously, but with the new version (2.1.8.RELEASE) I get this error (and no "OK" response):

org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'server.org.springframework.integration.config.ConsumerEndpointFactoryBean#1', and its 'requiresReply' property is set to true.
[...]

What I have found is that the ConversionService has been remplaced by MessageConverter and now Jackson is used to transform message from one type to another.

[...]

As @artembilan answered this is a workaround:

@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)));
}
@Kruschenstein Kruschenstein changed the title Spring Integration 5.1 - integration flow convertion with @IntegrationConverter don't work Spring Integration 5.1 - integration flow convertion with @IntegrationConverter doesn't work Sep 13, 2019
@artembilan artembilan added this to the 5.1.8 milestone Sep 13, 2019
@artembilan artembilan self-assigned this Sep 13, 2019
artembilan added a commit to artembilan/spring-integration that referenced this issue Sep 13, 2019
Fixes spring-projects#3052

Starting with version `5.1`, a `LambdaMessageProcessor` is based on the
`MessageConverter` instead of plain `ConversionService`.
(A `ConfigurableCompositeMessageConverter` is used from the application
context.)
However a type conversion based on the `@IntegrationConverter` is lost
in the `GenericMessageConverter`  because it doesn't use an
`integrationConversionService` from the application context

* Change `ConfigurableCompositeMessageConverter` to configure a
 `GenericMessageConverter`  with an  `integrationConversionService`
 if any
* Fix `MessagingMethodInvokerHelper` to populate a `BeanFactory` into
its internal `ConfigurableCompositeMessageConverter`
* Ensure in the `LambdaMessageProcessorTests` that
`@IntegrationConverter` is applied for ``LambdaMessageProcessor` as well

**Cherry-pick to 5.1.x**
garyrussell pushed a commit that referenced this issue Sep 13, 2019
Fixes #3052

Starting with version `5.1`, a `LambdaMessageProcessor` is based on the
`MessageConverter` instead of plain `ConversionService`.
(A `ConfigurableCompositeMessageConverter` is used from the application
context.)
However a type conversion based on the `@IntegrationConverter` is lost
in the `GenericMessageConverter`  because it doesn't use an
`integrationConversionService` from the application context

* Change `ConfigurableCompositeMessageConverter` to configure a
 `GenericMessageConverter`  with an  `integrationConversionService`
 if any
* Fix `MessagingMethodInvokerHelper` to populate a `BeanFactory` into
its internal `ConfigurableCompositeMessageConverter`
* Ensure in the `LambdaMessageProcessorTests` that
`@IntegrationConverter` is applied for ``LambdaMessageProcessor` as well

**Cherry-pick to 5.1.x**
artembilan added a commit that referenced this issue Sep 13, 2019
Fixes #3052

Starting with version `5.1`, a `LambdaMessageProcessor` is based on the
`MessageConverter` instead of plain `ConversionService`.
(A `ConfigurableCompositeMessageConverter` is used from the application
context.)
However a type conversion based on the `@IntegrationConverter` is lost
in the `GenericMessageConverter`  because it doesn't use an
`integrationConversionService` from the application context

* Change `ConfigurableCompositeMessageConverter` to configure a
 `GenericMessageConverter`  with an  `integrationConversionService`
 if any
* Fix `MessagingMethodInvokerHelper` to populate a `BeanFactory` into
its internal `ConfigurableCompositeMessageConverter`
* Ensure in the `LambdaMessageProcessorTests` that
`@IntegrationConverter` is applied for ``LambdaMessageProcessor` as well

**Cherry-pick to 5.1.x**

# Conflicts:
#	spring-integration-core/src/main/java/org/springframework/integration/handler/support/MessagingMethodInvokerHelper.java
#	spring-integration-core/src/test/java/org/springframework/integration/dsl/LambdaMessageProcessorTests.java
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants