Gateway: Propagate Error to the errorChannel

See SO for more info:
https://stackoverflow.com/questions/64456946/handle-exceptions-errors-other-than-messagingexception-ie-other-error-excepti

In the versions before `5.2.x` the `Error` was wrapped to the `MessagingException`
in the `AbstractRequestHandlerAdvice` and this one was handled properly
on the gateway level with its `errorChannel` configured

* Fix `MessagingGatewaySupport` to catch all the `Throwable` and try to send them as `ErrorMessage`
to the `errorChannel`.
Otherwise unwrap returned `MessagingException` and re-throw an `Error` as is to keep
the current behavior for non-handled exceptions

* Do not wrap `Error` into a `MessagingException` and re-throw as is if there is no `errorChannel`

**Cherry-pick to 5.3.x & 5.2.x**
This commit is contained in:
Artem Bilan
2020-10-22 11:41:34 -04:00
parent d60f23549c
commit 3b60e45679
2 changed files with 11 additions and 11 deletions

View File

@@ -526,7 +526,7 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint
throwMessageTimeoutException(object, "No reply received within timeout");
}
}
catch (Exception ex) {
catch (Throwable ex) { // NOSONAR (catch throwable)
if (logger.isDebugEnabled()) {
logger.debug("failure occurred in gateway sendAndReceive: " + ex.getMessage());
}
@@ -561,6 +561,9 @@ public abstract class MessagingGatewaySupport extends AbstractEndpoint
: errorFlowReply;
}
}
else if (error instanceof Error) {
throw (Error) error;
}
else {
Throwable errorToReThrow = error;
if (error instanceof MessagingException &&

View File

@@ -17,7 +17,7 @@
package org.springframework.integration.gateway;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.Mockito.mock;
import java.time.Duration;
@@ -27,7 +27,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.annotation.Gateway;
@@ -88,13 +88,10 @@ public class AsyncGatewayTests {
proxyFactory.afterPropertiesSet();
TestEchoService service = (TestEchoService) proxyFactory.getObject();
Future<Message<?>> f = service.returnMessage("foo");
try {
f.get(10000, TimeUnit.MILLISECONDS);
fail("Expected Exception");
}
catch (ExecutionException e) {
assertThat(e.getCause()).isEqualTo(error);
}
assertThatExceptionOfType(ExecutionException.class)
.isThrownBy(() -> f.get(10000, TimeUnit.MILLISECONDS))
.withCause(error);
}
@Test
@@ -134,7 +131,7 @@ public class AsyncGatewayTests {
}
@Test
public void customFutureReturned() throws Exception {
public void customFutureReturned() {
QueueChannel requestChannel = new QueueChannel();
addThreadEnricher(requestChannel);
startResponder(requestChannel);