mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Revise target bean exception with consistent message formatting
This commit is contained in:
@@ -390,19 +390,18 @@ public class HandlerMethod extends AnnotatedMethod {
|
||||
// Support methods for use in subclass variants
|
||||
|
||||
/**
|
||||
* Assert that the target bean class is an instance of the class where the given
|
||||
* method is declared. In some cases the actual controller instance at request-
|
||||
* processing time may be a JDK dynamic proxy (lazy initialization, prototype
|
||||
* beans, and others). {@code @Controller}'s that require proxying should prefer
|
||||
* class-based proxy mechanisms.
|
||||
* Assert that the target bean class is an instance of the class where the given method
|
||||
* is declared. In some cases the actual controller instance at request-processing time
|
||||
* may be a JDK dynamic proxy (lazy initialization, prototype beans, and others).
|
||||
* {@code @Controller}'s that require proxying should prefer class-based proxy mechanisms.
|
||||
*/
|
||||
protected void assertTargetBean(Method method, Object targetBean, Object[] args) {
|
||||
Class<?> methodDeclaringClass = method.getDeclaringClass();
|
||||
Class<?> targetBeanClass = targetBean.getClass();
|
||||
if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {
|
||||
String text = "The mapped handler method class '" + methodDeclaringClass.getName() +
|
||||
"' is not an instance of the actual controller bean class '" +
|
||||
targetBeanClass.getName() + "'. If the controller requires proxying " +
|
||||
"' is not an instance of the actual target bean class '" +
|
||||
targetBeanClass.getName() + "'. If the target bean requires proxying " +
|
||||
"(for example, due to @Transactional), please use class-based proxying.";
|
||||
throw new IllegalStateException(formatInvokeError(text, args));
|
||||
}
|
||||
@@ -410,12 +409,15 @@ public class HandlerMethod extends AnnotatedMethod {
|
||||
|
||||
protected String formatInvokeError(String text, Object[] args) {
|
||||
String formattedArgs = IntStream.range(0, args.length)
|
||||
.mapToObj(i -> (args[i] != null ?
|
||||
"[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" :
|
||||
"[" + i + "] [null]"))
|
||||
.collect(Collectors.joining(",\n", " ", " "));
|
||||
.mapToObj(i -> {
|
||||
Object arg = args[i];
|
||||
return (arg != null ?
|
||||
"[" + i + "] [type=" + arg.getClass().getName() + "] [value=" + arg + "]" :
|
||||
"[" + i + "] [null]");
|
||||
})
|
||||
.collect(Collectors.joining(",\n"));
|
||||
return text + "\n" +
|
||||
"Controller [" + getBeanType().getName() + "]\n" +
|
||||
"Handler [" + getBeanType().getName() + "]\n" +
|
||||
"Method [" + getBridgedMethod().toGenericString() + "] " +
|
||||
"with argument values:\n" + formattedArgs;
|
||||
}
|
||||
|
||||
+24
-26
@@ -49,7 +49,7 @@ class InvocableHandlerMethodTests {
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
void setup() {
|
||||
this.request = new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
@@ -82,9 +82,9 @@ class InvocableHandlerMethodTests {
|
||||
|
||||
@Test
|
||||
void cannotResolveArg() {
|
||||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
getInvocable(Integer.class, String.class).invokeForRequest(request, null))
|
||||
.withMessageContaining("Could not resolve parameter [0]");
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> getInvocable(Integer.class, String.class).invokeForRequest(request, null))
|
||||
.withMessageContaining("Could not resolve parameter [0]");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -108,54 +108,53 @@ class InvocableHandlerMethodTests {
|
||||
@Test
|
||||
void exceptionInResolvingArg() {
|
||||
this.composite.addResolver(new ExceptionRaisingArgumentResolver());
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
getInvocable(Integer.class, String.class).invokeForRequest(request, null));
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> getInvocable(Integer.class, String.class).invokeForRequest(request, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void illegalArgumentException() {
|
||||
this.composite.addResolver(new StubArgumentResolver(Integer.class, "__not_an_int__"));
|
||||
this.composite.addResolver(new StubArgumentResolver("value"));
|
||||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
getInvocable(Integer.class, String.class).invokeForRequest(request, null))
|
||||
.withCauseInstanceOf(IllegalArgumentException.class)
|
||||
.withMessageContaining("Controller [")
|
||||
.withMessageContaining("Method [")
|
||||
.withMessageContaining("with argument values:")
|
||||
.withMessageContaining("[0] [type=java.lang.String] [value=__not_an_int__]")
|
||||
.withMessageContaining("[1] [type=java.lang.String] [value=value");
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> getInvocable(Integer.class, String.class).invokeForRequest(request, null))
|
||||
.withCauseInstanceOf(IllegalArgumentException.class)
|
||||
.withMessageContaining("[" + Handler.class.getName() + "]")
|
||||
.withMessageContaining(Handler.class.getName() + ".handle")
|
||||
.withMessageContaining("[0] [type=java.lang.String] [value=__not_an_int__]")
|
||||
.withMessageContaining("[1] [type=java.lang.String] [value=value");
|
||||
}
|
||||
|
||||
@Test
|
||||
void invocationTargetException() {
|
||||
RuntimeException runtimeException = new RuntimeException("error");
|
||||
assertThatRuntimeException()
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, runtimeException))
|
||||
.isSameAs(runtimeException);
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, runtimeException))
|
||||
.isSameAs(runtimeException);
|
||||
|
||||
Error error = new Error("error");
|
||||
assertThatExceptionOfType(Error.class)
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, error))
|
||||
.isSameAs(error);
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, error))
|
||||
.isSameAs(error);
|
||||
|
||||
Exception exception = new Exception("error");
|
||||
assertThatException()
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, exception))
|
||||
.isSameAs(exception);
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, exception))
|
||||
.isSameAs(exception);
|
||||
|
||||
Throwable throwable = new Throwable("error");
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, throwable))
|
||||
.withCause(throwable)
|
||||
.withMessageContaining("Invocation failure");
|
||||
.isThrownBy(() -> getInvocable(Throwable.class).invokeForRequest(this.request, null, throwable))
|
||||
.withCause(throwable)
|
||||
.withMessageContaining("Invocation failure");
|
||||
}
|
||||
|
||||
@Test // SPR-13917
|
||||
void invocationErrorMessage() {
|
||||
this.composite.addResolver(new StubArgumentResolver(double.class));
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> getInvocable(double.class).invokeForRequest(this.request, null))
|
||||
.withMessageContaining("Illegal argument");
|
||||
.isThrownBy(() -> getInvocable(double.class).invokeForRequest(this.request, null))
|
||||
.withMessageContaining("Illegal argument");
|
||||
}
|
||||
|
||||
private InvocableHandlerMethod getInvocable(Class<?>... argTypes) {
|
||||
@@ -170,7 +169,6 @@ class InvocableHandlerMethodTests {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class Handler {
|
||||
|
||||
|
||||
+11
-12
@@ -117,8 +117,8 @@ class InvocableHandlerMethodTests {
|
||||
Mono<HandlerResult> mono = invoke(new TestController(), method);
|
||||
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(mono::block)
|
||||
.withMessage("Could not resolve parameter [0] in %s: No suitable resolver", method.toGenericString());
|
||||
.isThrownBy(mono::block)
|
||||
.withMessage("Could not resolve parameter [0] in %s: No suitable resolver", method.toGenericString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,8 +145,8 @@ class InvocableHandlerMethodTests {
|
||||
Mono<HandlerResult> mono = invoke(new TestController(), method);
|
||||
|
||||
assertThatExceptionOfType(UnsupportedMediaTypeStatusException.class)
|
||||
.isThrownBy(mono::block)
|
||||
.withMessage("415 UNSUPPORTED_MEDIA_TYPE \"boo\"");
|
||||
.isThrownBy(mono::block)
|
||||
.withMessage("415 UNSUPPORTED_MEDIA_TYPE \"boo\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,12 +156,11 @@ class InvocableHandlerMethodTests {
|
||||
Mono<HandlerResult> mono = invoke(new TestController(), method);
|
||||
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(mono::block)
|
||||
.withCauseInstanceOf(IllegalArgumentException.class)
|
||||
.withMessageContaining("Controller [")
|
||||
.withMessageContaining("Method [")
|
||||
.withMessageContaining("with argument values:")
|
||||
.withMessageContaining("[0] [type=java.lang.Integer] [value=1]");
|
||||
.isThrownBy(mono::block)
|
||||
.withCauseInstanceOf(IllegalArgumentException.class)
|
||||
.withMessageContaining("[" + TestController.class.getName() + "]")
|
||||
.withMessageContaining(TestController.class.getName() + ".singleArg")
|
||||
.withMessageContaining("[0] [type=java.lang.Integer] [value=1]");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -170,8 +169,8 @@ class InvocableHandlerMethodTests {
|
||||
Mono<HandlerResult> mono = invoke(new TestController(), method);
|
||||
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(mono::block)
|
||||
.withMessage("boo");
|
||||
.isThrownBy(mono::block)
|
||||
.withMessage("boo");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user