I was working on the Spring Boot Update to 3.0.1 and with it the Upgrade of Spring Integration 6.0.0 and Spring Cloud Stream 4.0.0. After upgrading however my previously working Spring Integration Flow is failing with underlying ClassCastException:
class org.springframework.messaging.handler.HandlerMethod$HandlerMethodParameter cannot be cast to class java.lang.reflect.Type (org.springframework.messaging.handler.HandlerMethod$HandlerMethodParameter is in unnamed module of loader 'app'; java.lang.reflect.Type is in module java.base of loader 'bootstrap')
Update: The exception originates from JsonMessageConverter inside of Spring Cloud Function Context, when trying to cast an object conversionHint (in my case of type HandlerMethodParameter) to Type.
Cannot cast 'org.springframework.messaging.handler.HandlerMethod$HandlerMethodParameter' to 'java.lang.reflect.Type'
Any hints or suggestions as to what might be the problem are highly appreciated.
Following is a highly shortened version of the affected integration flow and corresponding code snippets and a more detailed explanation:
@Bean
IntegrationFlow extract(SessionFactory<SftpClient.DirEntry> sftpSessionFactory,
XmlFileTransformer xmlFileTransformer){
return IntegrationFlow
.from(Sftp.inboundAdapter(sftpSessionFactory)
.preserveTimestamp(true)
.remoteDirectory("foo")
.regexFilter(".*\\.txt$")
.localDirectory(new File("sftp-inbound")), e -> e.id("sftpInboundAdapter")
.autoStartup(true)
.poller(Pollers.fixedDelay(5000))
)
.log(LoggingHandler.Level.DEBUG, "ExtractFlow", m -> "Successfully reached")
.wireTap(MONITORING_FLOW)
.log(LoggingHandler.Level.DEBUG, "ExtractFlow", m -> "Successfully done wire tap")
.transform(xmlFileTransformer)
.log(LoggingHandler.Level.DEBUG, "ExtractFlow", m -> "Successfully done transformation")
.handle(m -> xmlProcessor.process((XmlFile) m.getPayload())
.get();
}
@RequiredArgsConstructor
@Component
public class XmlFileTransformer implements GenericTransformer<Message<File>, XmlFile> {
@Override
public XmlFile transform(Message<File> message) {
return new XmlFile(message.getPayload().toPath(), message.getHeaders().get("x-origin", String.class));
}
}
The Integration Flow from the wiretap again transforms by implementing GenericTransfomer (similary written as XmlFileTransformer and then uses Amqp.outboundAdapter to send messages.
The method xmlProcessor.process
takes XmlFile
as argument. However it never reaches the actual method because it breaks when trying to go through the wire tap, and in case I comment the wire tap it breaks when trying to transform with xmlFileTransformer. So after log message "Successfully reached" the exception happens.
I'm using following relevant dependencies (other used dependencies not listed for better overview):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-sftp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-xml</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-amqp</artifactId>
</dependency>
</dependencies>
I was checking and rechecking my dependencies to ensure that I don't have any old dependencies that might clash with the update. However those should be fine as I'm using mostly the versions from spring-boot-starter-parent.
According to the migration guide of Spring Integration 6.0.0 there shouldn't be any major breaks that I forgot to handle. I was trying to find any information about similar cases however it seems not too many have either tried to upgrade to Spring Boot 3 yet or just didn't have the same issues as me. Could this be a bug in Spring Integration or do I need to refactor code so it's still running in Spring Integration 6.0? Or did I overlook issues with my dependencies?