Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

Am I wrongly using type casting with integration flow? Do you have a new solution for casting object with the new version? Or is this just a regression?

Thanks in advance!

like image 777
Kruschenstein Avatar asked Sep 12 '19 16:09

Kruschenstein


1 Answers

This is a bug in Spring Integration. We just don't use a proper ConversionService in the GenericMessageConverter.

Please, raise a GH issue on the matter.

Meanwhile a workaround for you is like this:

@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)));
}

So, we override whatever is configured by the framework and inject a proper IntegrationUtils.INTEGRATION_CONVERSION_SERVICE_BEAN_NAME bean which is supplied with your @IntegrationConverter component.

like image 197
Artem Bilan Avatar answered Sep 30 '22 14:09

Artem Bilan