Search code examples
spring-integration

Spring Integration WebFlux inboundGateway replyChannel for error response


Trying to use the replyChannel for sending an error response for the WebFlux.inboundGateway, however no response is sent from ErrorFlow and the client continues to wait for response. Kindly suggest.

return IntegrationFlows.from(WebFlux.inboundGateway("/some/uri")
                                    .requestMapping(m -> m.methods(POST))
                                    .requestPayloadType(SomeObject.class)
                                    .replyChannel(webReplyChannel)
                                    .errorChannel(appErrorChannel))


@Bean
public IntegrationFlow appErrorFlow() {

    return IntegrationFlows.from(appErrorChannel())
                        .<ErrorMessage, Message<String>> transform(errorMessage -> MessageBuilder.withPayload("Error Response")
                                                                                        .copyHeaders(((MessagingException) errorMessage.getPayload()).getFailedMessage().getHeaders())
                                                                                        .build())
                        .get();

Exception:

2023-01-14 13:34:10,343 [reactor-http-nio-2        ] ERROR o.s.i.h.LambdaMessageProcessor - 1283c6fd42485bf5 Could not invoke the method 'public java.lang.Object com.xxxxxxxxxxx.xxxxx..ErrorFlowConfig$$Lambda$2129/0x0000000801ac3a00.transform(java.lang.Object)' due to a class cast exception, if using a lambda in the DSL, consider using an overloaded EIP method that takes a Class<?> argument to explicitly  specify the type. An example of when this often occurs is if the lambda is configured to receive a Message<?> argument.
java.lang.ClassCastException: class com.xxxxxxx.model.dto.SomeObject cannot be cast to class org.springframework.messaging.support.ErrorMessage (com.xxxxxxx.model.dto.SomeObject is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @32f93dff; org.springframework.messaging.support.ErrorMessage is in unnamed module of loader 'app')
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.integration.handler.LambdaMessageProcessor.processMessage(LambdaMessageProcessor.java:105)
    at org.springframework.integration.transformer.AbstractMessageProcessingTransformer.transform(AbstractMessageProcessingTransformer.java:115)
    at o

Solution

  • This is known framework limitation: https://github.com/spring-projects/spring-integration/issues/3984.

    So, for now you have to do like this instead:

    .transform(Message.class,
               errorMessage -> 
                           MessageBuilder.withPayload("Error Response")
                                    .copyHeaders(((MessagingException) errorMessage.getPayload()).getFailedMessage().getHeaders())
                                    .build())
    

    Only those getFailedMessage().getHeaders() contain respective replyChannel and errorChannel headers.