1
votes

Hey i'm sending messages out to an http endpoint and since i'll have to trigger an error flow on selective failures, i'm sending the message through a gateway before eventually routing it through an http outbound gateway.

@MessagingGateway(errorChannel="invocationFailureChannel")
public interface Invocator {
    @Gateway(requestChannel="invocationChannel")
    public Boolean invokeService(Message<String> invocation);
}

@Bean
public IntegrationFlow errorHandlingFlow() {
    return IntegrationFlows
            .from("invocationFailureChannel")
            .transform("payload.getFailedMessage()")
            .handle(new GenericHandler<Object>() {
                @Override
                public Object handle(Object payload, Map<String, Object> headers) {
                    //Do Stuff
                    return false;
                }
            })
            .get();
}

The reply from the error channel is supposed to ripple back to the bean that's actually invoking the gateway right? But i get this weird exception:

o.s.m.c.GenericMessagingTemplate$TemporaryReplyChannel - Reply message received but the receiving thread has exited due to an exception while sending the request message

I tried setting a timeout on both the request and reply, but that didn't really help. I tried to put an try-catch on the code that's calling the gateway, but i didn't get an error there either.

I even tried an example identical to the one shown in:

https://www.youtube.com/watch?v=mF2uq4DnVCg

I have no idea why it isn't working for me. I get the same error even in a sample example.

1

1 Answers

2
votes

When the gateway sends the error to the error channel, it has a new 'replyChannel` header; the old one is "spent" - it was used when the gateway received the error.

This line...

.transform("payload.getFailedMessage()")

is messing things up because transformers that return a message overwrite the headers, so the new reply channel gets replaced with the spent one.

You can use

.transform("payload.failedMessage.payload")

and the framework will take care of maintaining the headers. If you need access to the failedMessage headers, you will need a custom transformer, and you need to be sure to retain the "new" replyChannel header.

Or, you can copy individual headers from the failed message with a header enricher - .enrichHeaders(s -> s.headerExpression("foo", "payload.failedMessage.headers['foo']")) before the .transform().