Skip to content

Commit 2626930

Browse files
garyrussellartembilan
authored andcommittedDec 18, 2017
AMQP-794: CRErrorHandler: Traverse cause tree
JIRA: https://jira.spring.io/browse/AMQP-794 In the `ConditionalRejectingErrorHandleri.DefaultExceptionStrategy`, if the `cause` of the `ListenerExecutionFailedException` is a `MessagingException`, traverse the `cause` tree to find the root cause of all such exceptions unless it's a fatal cause itself (`MethodArgumentResolutionException` or `MessageConversionException`). The final fatal check is performed on the root cause.
1 parent 4b78c20 commit 2626930

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed
 

‎spring-rabbit/src/main/java/org/springframework/amqp/rabbit/listener/ConditionalRejectingErrorHandler.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
2323
import org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException;
2424
import org.springframework.amqp.support.converter.MessageConversionException;
25+
import org.springframework.messaging.MessagingException;
2526
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
2627
import org.springframework.messaging.handler.annotation.support.MethodArgumentTypeMismatchException;
28+
import org.springframework.messaging.handler.invocation.MethodArgumentResolutionException;
2729
import org.springframework.util.ErrorHandler;
2830

2931
/**
@@ -103,8 +105,14 @@ public static class DefaultExceptionStrategy implements FatalExceptionStrategy {
103105

104106
@Override
105107
public boolean isFatal(Throwable t) {
106-
if (t instanceof ListenerExecutionFailedException
107-
&& isCauseFatal(t.getCause())) {
108+
Throwable cause = t.getCause();
109+
while (cause instanceof MessagingException
110+
&& !(cause instanceof
111+
org.springframework.messaging.converter.MessageConversionException)
112+
&& !(cause instanceof MethodArgumentResolutionException)) {
113+
cause = cause.getCause();
114+
}
115+
if (t instanceof ListenerExecutionFailedException && isCauseFatal(cause)) {
108116
if (this.logger.isWarnEnabled()) {
109117
this.logger.warn(
110118
"Fatal message conversion error; message rejected; "
@@ -119,8 +127,7 @@ && isCauseFatal(t.getCause())) {
119127
private boolean isCauseFatal(Throwable cause) {
120128
return cause instanceof MessageConversionException
121129
|| cause instanceof org.springframework.messaging.converter.MessageConversionException
122-
|| cause instanceof MethodArgumentNotValidException
123-
|| cause instanceof MethodArgumentTypeMismatchException
130+
|| cause instanceof MethodArgumentResolutionException
124131
|| cause instanceof NoSuchMethodException
125132
|| cause instanceof ClassCastException
126133
|| isUserCauseFatal(cause);

‎spring-rabbit/src/test/java/org/springframework/amqp/rabbit/listener/ErrorHandlerTests.java

+35
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@
2727
import org.junit.Test;
2828

2929
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
30+
import org.springframework.amqp.core.MessageProperties;
3031
import org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException;
3132
import org.springframework.amqp.support.converter.MessageConversionException;
3233
import org.springframework.amqp.utils.test.TestUtils;
3334
import org.springframework.beans.DirectFieldAccessor;
3435
import org.springframework.core.MethodParameter;
3536
import org.springframework.messaging.Message;
37+
import org.springframework.messaging.MessageHandlingException;
3638
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException;
3739
import org.springframework.messaging.handler.annotation.support.MethodArgumentTypeMismatchException;
3840

@@ -92,6 +94,39 @@ public void testFatalsAreRejected() throws Exception {
9294
}
9395
}
9496

97+
@Test
98+
public void testSimple() {
99+
Throwable cause = new ClassCastException();
100+
try {
101+
doTest(cause);
102+
fail("Expected exception");
103+
}
104+
catch (AmqpRejectAndDontRequeueException e) {
105+
// noop
106+
}
107+
}
108+
109+
@Test
110+
public void testMessagingException() {
111+
Throwable cause = new MessageHandlingException(null, "test",
112+
new MessageHandlingException(null, "test", new ClassCastException()));
113+
try {
114+
doTest(cause);
115+
fail("Expected exception");
116+
}
117+
catch (AmqpRejectAndDontRequeueException e) {
118+
// noop
119+
}
120+
}
121+
122+
private void doTest(Throwable cause) {
123+
ConditionalRejectingErrorHandler handler = new ConditionalRejectingErrorHandler();
124+
handler.handleError(
125+
new ListenerExecutionFailedException("test", cause,
126+
new org.springframework.amqp.core.Message(new byte[0],
127+
new MessageProperties())));
128+
}
129+
95130
private static class Foo {
96131

97132
@SuppressWarnings("unused")

0 commit comments

Comments
 (0)
Please sign in to comment.