Skip to content

Commit e5de7d5

Browse files
committed
@MessageExceptionHandler matches cause as well (analogous to @ExceptionHandler)
Issue: SPR-14424
1 parent cfc560c commit e5de7d5

File tree

2 files changed

+43
-8
lines changed

2 files changed

+43
-8
lines changed

spring-messaging/src/main/java/org/springframework/messaging/handler/invocation/AbstractExceptionHandlerMethodResolver.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
* {@link ExceptionDepthComparator} and the top match is returned.
3434
*
3535
* @author Rossen Stoyanchev
36+
* @author Juergen Hoeller
3637
* @since 4.0
3738
*/
3839
public abstract class AbstractExceptionHandlerMethodResolver {
@@ -69,6 +70,7 @@ protected static List<Class<? extends Throwable>> getExceptionsFromMethodSignatu
6970
return result;
7071
}
7172

73+
7274
/**
7375
* Whether the contained type has any exception mappings.
7476
*/
@@ -77,13 +79,30 @@ public boolean hasExceptionMappings() {
7779
}
7880

7981
/**
80-
* Find a method to handle the given exception.
81-
* Use {@link org.springframework.core.ExceptionDepthComparator} if more than one match is found.
82+
* Find a {@link Method} to handle the given exception.
83+
* Use {@link ExceptionDepthComparator} if more than one match is found.
8284
* @param exception the exception
83-
* @return a method to handle the exception or {@code null}
85+
* @return a Method to handle the exception, or {@code null} if none found
8486
*/
8587
public Method resolveMethod(Exception exception) {
86-
Class<? extends Exception> exceptionType = exception.getClass();
88+
Method method = resolveMethodByExceptionType(exception.getClass());
89+
if (method == null) {
90+
Throwable cause = exception.getCause();
91+
if (cause != null) {
92+
method = resolveMethodByExceptionType(cause.getClass());
93+
}
94+
}
95+
return method;
96+
}
97+
98+
/**
99+
* Find a {@link Method} to handle the given exception type. This can be
100+
* useful if an {@link Exception} instance is not available (e.g. for tools).
101+
* @param exceptionType the exception type
102+
* @return a Method to handle the exception, or {@code null} if none found
103+
* @since 4.3.1
104+
*/
105+
public Method resolveMethodByExceptionType(Class<? extends Throwable> exceptionType) {
87106
Method method = this.exceptionLookupCache.get(exceptionType);
88107
if (method == null) {
89108
method = getMappedMethod(exceptionType);
@@ -93,9 +112,9 @@ public Method resolveMethod(Exception exception) {
93112
}
94113

95114
/**
96-
* Return the method mapped to the given exception type or {@code null}.
115+
* Return the {@link Method} mapped to the given exception type, or {@code null} if none.
97116
*/
98-
private Method getMappedMethod(Class<? extends Exception> exceptionType) {
117+
private Method getMappedMethod(Class<? extends Throwable> exceptionType) {
99118
List<Class<? extends Throwable>> matches = new ArrayList<Class<? extends Throwable>>();
100119
for (Class<? extends Throwable> mappedException : this.mappedMethods.keySet()) {
101120
if (mappedException.isAssignableFrom(exceptionType)) {

spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/AnnotationExceptionHandlerMethodResolverTests.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,7 @@
3333
* Test fixture for {@link AnnotationExceptionHandlerMethodResolver} tests.
3434
*
3535
* @author Rossen Stoyanchev
36+
* @author Juergen Hoeller
3637
*/
3738
public class AnnotationExceptionHandlerMethodResolverTests {
3839

@@ -50,6 +51,13 @@ public void resolveMethodFromArgument() {
5051
assertEquals("handleIllegalArgumentException", resolver.resolveMethod(exception).getName());
5152
}
5253

54+
@Test
55+
public void resolveMethodFromArgumentWithErrorType() {
56+
AnnotationExceptionHandlerMethodResolver resolver = new AnnotationExceptionHandlerMethodResolver(ExceptionController.class);
57+
AssertionError exception = new AssertionError();
58+
assertEquals("handleAssertionError", resolver.resolveMethod(new IllegalStateException(exception)).getName());
59+
}
60+
5361
@Test
5462
public void resolveMethodExceptionSubType() {
5563
AnnotationExceptionHandlerMethodResolver resolver = new AnnotationExceptionHandlerMethodResolver(ExceptionController.class);
@@ -91,6 +99,7 @@ public void noExceptionMapping() {
9199
new AnnotationExceptionHandlerMethodResolver(NoExceptionController.class);
92100
}
93101

102+
94103
@Controller
95104
static class ExceptionController {
96105

@@ -107,8 +116,13 @@ public void handleSocketException() {
107116
@MessageExceptionHandler
108117
public void handleIllegalArgumentException(IllegalArgumentException exception) {
109118
}
119+
120+
@MessageExceptionHandler
121+
public void handleAssertionError(AssertionError exception) {
122+
}
110123
}
111124

125+
112126
@Controller
113127
static class InheritedController extends ExceptionController {
114128

@@ -117,6 +131,7 @@ public void handleIOException() {
117131
}
118132
}
119133

134+
120135
@Controller
121136
static class AmbiguousController {
122137

@@ -133,6 +148,7 @@ public String handle2(IllegalArgumentException ex) {
133148
}
134149
}
135150

151+
136152
@Controller
137153
static class NoExceptionController {
138154

0 commit comments

Comments
 (0)