1
1
/*
2
- * Copyright 2002-2014 the original author or authors.
2
+ * Copyright 2002-2015 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
32
32
import org .springframework .web .method .HandlerMethod ;
33
33
34
34
/**
35
- * Provides a method for invoking the handler method for a given request after resolving its method argument
36
- * values through registered {@link HandlerMethodArgumentResolver}s.
35
+ * Provides a method for invoking the handler method for a given request after resolving its
36
+ * method argument values through registered {@link HandlerMethodArgumentResolver}s.
37
37
*
38
- * <p>Argument resolution often requires a {@link WebDataBinder} for data binding or for type conversion.
39
- * Use the {@link #setDataBinderFactory(WebDataBinderFactory)} property to supply a binder factory to pass to
40
- * argument resolvers.
38
+ * <p>Argument resolution often requires a {@link WebDataBinder} for data binding or for type
39
+ * conversion. Use the {@link #setDataBinderFactory(WebDataBinderFactory)} property to supply
40
+ * a binder factory to pass to argument resolvers.
41
41
*
42
- * <p>Use {@link #setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite)} to customize
43
- * the list of argument resolvers.
42
+ * <p>Use {@link #setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite)}
43
+ * to customize the list of argument resolvers.
44
44
*
45
45
* @author Rossen Stoyanchev
46
46
* @since 3.1
@@ -55,17 +55,17 @@ public class InvocableHandlerMethod extends HandlerMethod {
55
55
56
56
57
57
/**
58
- * Create an instance from the given handler and method .
58
+ * Create an instance from a {@code HandlerMethod} .
59
59
*/
60
- public InvocableHandlerMethod (Object bean , Method method ) {
61
- super (bean , method );
60
+ public InvocableHandlerMethod (HandlerMethod handlerMethod ) {
61
+ super (handlerMethod );
62
62
}
63
63
64
64
/**
65
- * Create an instance from a {@code HandlerMethod} .
65
+ * Create an instance from a bean instance and a method .
66
66
*/
67
- public InvocableHandlerMethod (HandlerMethod handlerMethod ) {
68
- super (handlerMethod );
67
+ public InvocableHandlerMethod (Object bean , Method method ) {
68
+ super (bean , method );
69
69
}
70
70
71
71
/**
@@ -75,7 +75,9 @@ public InvocableHandlerMethod(HandlerMethod handlerMethod) {
75
75
* @param parameterTypes the method parameter types
76
76
* @throws NoSuchMethodException when the method cannot be found
77
77
*/
78
- public InvocableHandlerMethod (Object bean , String methodName , Class <?>... parameterTypes ) throws NoSuchMethodException {
78
+ public InvocableHandlerMethod (Object bean , String methodName , Class <?>... parameterTypes )
79
+ throws NoSuchMethodException {
80
+
79
81
super (bean , methodName , parameterTypes );
80
82
}
81
83
@@ -107,16 +109,18 @@ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDisc
107
109
108
110
109
111
/**
110
- * Invoke the method after resolving its argument values in the context of the given request. <p>Argument
111
- * values are commonly resolved through {@link HandlerMethodArgumentResolver}s. The {@code provideArgs}
112
- * parameter however may supply argument values to be used directly, i.e. without argument resolution.
113
- * Examples of provided argument values include a {@link WebDataBinder}, a {@link SessionStatus}, or
114
- * a thrown exception instance. Provided argument values are checked before argument resolvers.
112
+ * Invoke the method after resolving its argument values in the context of the given request.
113
+ * <p>Argument values are commonly resolved through {@link HandlerMethodArgumentResolver}s.
114
+ * The {@code providedArgs} parameter however may supply argument values to be used directly,
115
+ * i.e. without argument resolution. Examples of provided argument values include a
116
+ * {@link WebDataBinder}, a {@link SessionStatus}, or a thrown exception instance.
117
+ * Provided argument values are checked before argument resolvers.
115
118
* @param request the current request
116
119
* @param mavContainer the ModelAndViewContainer for this request
117
120
* @param providedArgs "given" arguments matched by type, not resolved
118
121
* @return the raw value returned by the invoked method
119
- * @exception Exception raised if no suitable argument resolver can be found, or the method raised an exception
122
+ * @exception Exception raised if no suitable argument resolver can be found,
123
+ * or if the method raised an exception
120
124
*/
121
125
public final Object invokeForRequest (NativeWebRequest request , ModelAndViewContainer mavContainer ,
122
126
Object ... providedArgs ) throws Exception {
@@ -129,7 +133,7 @@ public final Object invokeForRequest(NativeWebRequest request, ModelAndViewConta
129
133
sb .append (Arrays .asList (args ));
130
134
logger .trace (sb .toString ());
131
135
}
132
- Object returnValue = invoke (args );
136
+ Object returnValue = doInvoke (args );
133
137
if (logger .isTraceEnabled ()) {
134
138
logger .trace ("Method [" + getMethod ().getName () + "] returned [" + returnValue + "]" );
135
139
}
@@ -159,8 +163,8 @@ private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewC
159
163
continue ;
160
164
}
161
165
catch (Exception ex ) {
162
- if (logger .isTraceEnabled ()) {
163
- logger .trace (getArgumentResolutionErrorMessage ("Error resolving argument" , i ), ex );
166
+ if (logger .isDebugEnabled ()) {
167
+ logger .debug (getArgumentResolutionErrorMessage ("Error resolving argument" , i ), ex );
164
168
}
165
169
throw ex ;
166
170
}
@@ -180,7 +184,8 @@ private String getArgumentResolutionErrorMessage(String message, int index) {
180
184
}
181
185
182
186
/**
183
- * Adds HandlerMethod details such as the controller type and method signature to the given error message.
187
+ * Adds HandlerMethod details such as the controller type and method
188
+ * signature to the given error message.
184
189
* @param message error message to append the HandlerMethod details to
185
190
*/
186
191
protected String getDetailedErrorMessage (String message ) {
@@ -206,17 +211,19 @@ private Object resolveProvidedArgument(MethodParameter parameter, Object... prov
206
211
return null ;
207
212
}
208
213
214
+
209
215
/**
210
216
* Invoke the handler method with the given argument values.
211
217
*/
212
- private Object invoke (Object ... args ) throws Exception {
218
+ protected Object doInvoke (Object ... args ) throws Exception {
213
219
ReflectionUtils .makeAccessible (getBridgedMethod ());
214
220
try {
215
221
return getBridgedMethod ().invoke (getBean (), args );
216
222
}
217
223
catch (IllegalArgumentException ex ) {
218
224
assertTargetBean (getBridgedMethod (), getBean (), args );
219
- throw new IllegalStateException (getInvocationErrorMessage (ex .getMessage (), args ), ex );
225
+ String message = (ex .getMessage () != null ? ex .getMessage () : "Illegal argument" );
226
+ throw new IllegalStateException (getInvocationErrorMessage (message , args ), ex );
220
227
}
221
228
catch (InvocationTargetException ex ) {
222
229
// Unwrap for HandlerExceptionResolvers ...
@@ -249,7 +256,7 @@ private void assertTargetBean(Method method, Object targetBean, Object[] args) {
249
256
Class <?> targetBeanClass = targetBean .getClass ();
250
257
if (!methodDeclaringClass .isAssignableFrom (targetBeanClass )) {
251
258
String msg = "The mapped controller method class '" + methodDeclaringClass .getName () +
252
- "' is not an instance of the actual controller bean instance '" +
259
+ "' is not an instance of the actual controller bean class '" +
253
260
targetBeanClass .getName () + "'. If the controller requires proxying " +
254
261
"(e.g. due to @Transactional), please use class-based proxying." ;
255
262
throw new IllegalStateException (getInvocationErrorMessage (msg , args ));
@@ -259,7 +266,7 @@ private void assertTargetBean(Method method, Object targetBean, Object[] args) {
259
266
private String getInvocationErrorMessage (String message , Object [] resolvedArgs ) {
260
267
StringBuilder sb = new StringBuilder (getDetailedErrorMessage (message ));
261
268
sb .append ("Resolved arguments: \n " );
262
- for (int i = 0 ; i < resolvedArgs .length ; i ++) {
269
+ for (int i = 0 ; i < resolvedArgs .length ; i ++) {
263
270
sb .append ("[" ).append (i ).append ("] " );
264
271
if (resolvedArgs [i ] == null ) {
265
272
sb .append ("[null] \n " );
0 commit comments