Skip to content

Commit 3f42e16

Browse files
committed
Increase sharing among InvocableHandlerMethod variants
In particular between reactive and non-reactive web variants, but also preparing for a messaing reactive variant.
1 parent 7c36549 commit 3f42e16

File tree

5 files changed

+112
-160
lines changed

5 files changed

+112
-160
lines changed

spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.Method;
21+
import java.util.stream.Collectors;
22+
import java.util.stream.IntStream;
2123

2224
import org.apache.commons.logging.Log;
2325
import org.apache.commons.logging.LogFactory;
@@ -31,6 +33,8 @@
3133
import org.springframework.lang.Nullable;
3234
import org.springframework.util.Assert;
3335
import org.springframework.util.ClassUtils;
36+
import org.springframework.util.ObjectUtils;
37+
import org.springframework.util.StringUtils;
3438

3539
/**
3640
* Encapsulates information about a handler method consisting of a
@@ -321,6 +325,59 @@ public String toString() {
321325
}
322326

323327

328+
// Support methods for use in "InvocableHandlerMethod" sub-class variants..
329+
330+
@Nullable
331+
protected static Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
332+
if (!ObjectUtils.isEmpty(providedArgs)) {
333+
for (Object providedArg : providedArgs) {
334+
if (parameter.getParameterType().isInstance(providedArg)) {
335+
return providedArg;
336+
}
337+
}
338+
}
339+
return null;
340+
}
341+
342+
protected static String formatArgumentError(MethodParameter param, String message) {
343+
return "Could not resolve parameter [" + param.getParameterIndex() + "] in " +
344+
param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : "");
345+
}
346+
347+
/**
348+
* Assert that the target bean class is an instance of the class where the given
349+
* method is declared. In some cases the actual endpoint instance at request-
350+
* processing time may be a JDK dynamic proxy (lazy initialization, prototype
351+
* beans, and others). Endpoint classes that require proxying should prefer
352+
* class-based proxy mechanisms.
353+
*/
354+
protected void assertTargetBean(Method method, Object targetBean, Object[] args) {
355+
Class<?> methodDeclaringClass = method.getDeclaringClass();
356+
Class<?> targetBeanClass = targetBean.getClass();
357+
if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {
358+
String text = "The mapped handler method class '" + methodDeclaringClass.getName() +
359+
"' is not an instance of the actual endpoint bean class '" +
360+
targetBeanClass.getName() + "'. If the endpoint requires proxying " +
361+
"(e.g. due to @Transactional), please use class-based proxying.";
362+
throw new IllegalStateException(formatInvokeError(text, args));
363+
}
364+
}
365+
366+
protected String formatInvokeError(String text, Object[] args) {
367+
368+
String formattedArgs = IntStream.range(0, args.length)
369+
.mapToObj(i -> (args[i] != null ?
370+
"[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" :
371+
"[" + i + "] [null]"))
372+
.collect(Collectors.joining(",\n", " ", " "));
373+
374+
return text + "\n" +
375+
"Endpoint [" + getBeanType().getName() + "]\n" +
376+
"Method [" + getBridgedMethod().toGenericString() + "] " +
377+
"with argument values:\n" + formattedArgs;
378+
}
379+
380+
324381
/**
325382
* A MethodParameter with HandlerMethod-specific behavior.
326383
*/

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

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import java.lang.reflect.Method;
2121
import java.lang.reflect.Type;
2222
import java.util.Arrays;
23-
import java.util.stream.Collectors;
24-
import java.util.stream.IntStream;
2523

2624
import org.springframework.core.DefaultParameterNameDiscoverer;
2725
import org.springframework.core.MethodParameter;
@@ -32,7 +30,6 @@
3230
import org.springframework.messaging.handler.HandlerMethod;
3331
import org.springframework.util.ObjectUtils;
3432
import org.springframework.util.ReflectionUtils;
35-
import org.springframework.util.StringUtils;
3633

3734
/**
3835
* Extension of {@link HandlerMethod} that invokes the underlying method with
@@ -163,23 +160,6 @@ protected Object[] getMethodArgumentValues(Message<?> message, Object... provide
163160
return args;
164161
}
165162

166-
@Nullable
167-
private Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
168-
if (!ObjectUtils.isEmpty(providedArgs)) {
169-
for (Object providedArg : providedArgs) {
170-
if (parameter.getParameterType().isInstance(providedArg)) {
171-
return providedArg;
172-
}
173-
}
174-
}
175-
return null;
176-
}
177-
178-
private static String formatArgumentError(MethodParameter param, String message) {
179-
return "Could not resolve parameter [" + param.getParameterIndex() + "] in " +
180-
param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : "");
181-
}
182-
183163
/**
184164
* Invoke the handler method with the given argument values.
185165
*/
@@ -212,39 +192,6 @@ else if (targetException instanceof Exception) {
212192
}
213193
}
214194

215-
/**
216-
* Assert that the target bean class is an instance of the class where the given
217-
* method is declared. In some cases the actual endpoint instance at request-
218-
* processing time may be a JDK dynamic proxy (lazy initialization, prototype
219-
* beans, and others). Endpoint classes that require proxying should prefer
220-
* class-based proxy mechanisms.
221-
*/
222-
private void assertTargetBean(Method method, Object targetBean, Object[] args) {
223-
Class<?> methodDeclaringClass = method.getDeclaringClass();
224-
Class<?> targetBeanClass = targetBean.getClass();
225-
if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {
226-
String text = "The mapped handler method class '" + methodDeclaringClass.getName() +
227-
"' is not an instance of the actual endpoint bean class '" +
228-
targetBeanClass.getName() + "'. If the endpoint requires proxying " +
229-
"(e.g. due to @Transactional), please use class-based proxying.";
230-
throw new IllegalStateException(formatInvokeError(text, args));
231-
}
232-
}
233-
234-
private String formatInvokeError(String text, Object[] args) {
235-
236-
String formattedArgs = IntStream.range(0, args.length)
237-
.mapToObj(i -> (args[i] != null ?
238-
"[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" :
239-
"[" + i + "] [null]"))
240-
.collect(Collectors.joining(",\n", " ", " "));
241-
242-
return text + "\n" +
243-
"Endpoint [" + getBeanType().getName() + "]\n" +
244-
"Method [" + getBridgedMethod().toGenericString() + "] " +
245-
"with argument values:\n" + formattedArgs;
246-
}
247-
248195
MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
249196
return new AsyncResultMethodParameter(returnValue);
250197
}

spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.util.ArrayList;
2222
import java.util.Arrays;
2323
import java.util.List;
24+
import java.util.stream.Collectors;
25+
import java.util.stream.IntStream;
2426

2527
import org.apache.commons.logging.Log;
2628
import org.apache.commons.logging.LogFactory;
@@ -36,6 +38,8 @@
3638
import org.springframework.lang.Nullable;
3739
import org.springframework.util.Assert;
3840
import org.springframework.util.ClassUtils;
41+
import org.springframework.util.ObjectUtils;
42+
import org.springframework.util.StringUtils;
3943
import org.springframework.web.bind.annotation.ResponseStatus;
4044

4145
/**
@@ -172,7 +176,6 @@ private HandlerMethod(HandlerMethod handlerMethod, Object handler) {
172176
this.resolvedFromHandlerMethod = handlerMethod;
173177
}
174178

175-
176179
private MethodParameter[] initMethodParameters() {
177180
int count = this.bridgedMethod.getParameterCount();
178181
MethodParameter[] result = new MethodParameter[count];
@@ -390,6 +393,57 @@ public String toString() {
390393
}
391394

392395

396+
// Support methods for use in "InvocableHandlerMethod" sub-class variants..
397+
398+
@Nullable
399+
protected static Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
400+
if (!ObjectUtils.isEmpty(providedArgs)) {
401+
for (Object providedArg : providedArgs) {
402+
if (parameter.getParameterType().isInstance(providedArg)) {
403+
return providedArg;
404+
}
405+
}
406+
}
407+
return null;
408+
}
409+
410+
protected static String formatArgumentError(MethodParameter param, String message) {
411+
return "Could not resolve parameter [" + param.getParameterIndex() + "] in " +
412+
param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : "");
413+
}
414+
415+
/**
416+
* Assert that the target bean class is an instance of the class where the given
417+
* method is declared. In some cases the actual controller instance at request-
418+
* processing time may be a JDK dynamic proxy (lazy initialization, prototype
419+
* beans, and others). {@code @Controller}'s that require proxying should prefer
420+
* class-based proxy mechanisms.
421+
*/
422+
protected void assertTargetBean(Method method, Object targetBean, Object[] args) {
423+
Class<?> methodDeclaringClass = method.getDeclaringClass();
424+
Class<?> targetBeanClass = targetBean.getClass();
425+
if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {
426+
String text = "The mapped handler method class '" + methodDeclaringClass.getName() +
427+
"' is not an instance of the actual controller bean class '" +
428+
targetBeanClass.getName() + "'. If the controller requires proxying " +
429+
"(e.g. due to @Transactional), please use class-based proxying.";
430+
throw new IllegalStateException(formatInvokeError(text, args));
431+
}
432+
}
433+
434+
protected String formatInvokeError(String text, Object[] args) {
435+
String formattedArgs = IntStream.range(0, args.length)
436+
.mapToObj(i -> (args[i] != null ?
437+
"[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" :
438+
"[" + i + "] [null]"))
439+
.collect(Collectors.joining(",\n", " ", " "));
440+
return text + "\n" +
441+
"Controller [" + getBeanType().getName() + "]\n" +
442+
"Method [" + getBridgedMethod().toGenericString() + "] " +
443+
"with argument values:\n" + formattedArgs;
444+
}
445+
446+
393447
/**
394448
* A MethodParameter with HandlerMethod-specific behavior.
395449
*/

spring-web/src/main/java/org/springframework/web/method/support/InvocableHandlerMethod.java

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,13 @@
1919
import java.lang.reflect.InvocationTargetException;
2020
import java.lang.reflect.Method;
2121
import java.util.Arrays;
22-
import java.util.stream.Collectors;
23-
import java.util.stream.IntStream;
2422

2523
import org.springframework.core.DefaultParameterNameDiscoverer;
2624
import org.springframework.core.MethodParameter;
2725
import org.springframework.core.ParameterNameDiscoverer;
2826
import org.springframework.lang.Nullable;
2927
import org.springframework.util.ObjectUtils;
3028
import org.springframework.util.ReflectionUtils;
31-
import org.springframework.util.StringUtils;
3229
import org.springframework.web.bind.WebDataBinder;
3330
import org.springframework.web.bind.support.SessionStatus;
3431
import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -182,23 +179,6 @@ protected Object[] getMethodArgumentValues(NativeWebRequest request, @Nullable M
182179
return args;
183180
}
184181

185-
@Nullable
186-
private Object findProvidedArgument(MethodParameter parameter, @Nullable Object... providedArgs) {
187-
if (!ObjectUtils.isEmpty(providedArgs)) {
188-
for (Object providedArg : providedArgs) {
189-
if (parameter.getParameterType().isInstance(providedArg)) {
190-
return providedArg;
191-
}
192-
}
193-
}
194-
return null;
195-
}
196-
197-
private static String formatArgumentError(MethodParameter param, String message) {
198-
return "Could not resolve parameter [" + param.getParameterIndex() + "] in " +
199-
param.getExecutable().toGenericString() + (StringUtils.hasText(message) ? ": " + message : "");
200-
}
201-
202182
/**
203183
* Invoke the handler method with the given argument values.
204184
*/
@@ -231,37 +211,4 @@ else if (targetException instanceof Exception) {
231211
}
232212
}
233213

234-
/**
235-
* Assert that the target bean class is an instance of the class where the given
236-
* method is declared. In some cases the actual controller instance at request-
237-
* processing time may be a JDK dynamic proxy (lazy initialization, prototype
238-
* beans, and others). {@code @Controller}'s that require proxying should prefer
239-
* class-based proxy mechanisms.
240-
*/
241-
private void assertTargetBean(Method method, Object targetBean, Object[] args) {
242-
Class<?> methodDeclaringClass = method.getDeclaringClass();
243-
Class<?> targetBeanClass = targetBean.getClass();
244-
if (!methodDeclaringClass.isAssignableFrom(targetBeanClass)) {
245-
String text = "The mapped handler method class '" + methodDeclaringClass.getName() +
246-
"' is not an instance of the actual controller bean class '" +
247-
targetBeanClass.getName() + "'. If the controller requires proxying " +
248-
"(e.g. due to @Transactional), please use class-based proxying.";
249-
throw new IllegalStateException(formatInvokeError(text, args));
250-
}
251-
}
252-
253-
private String formatInvokeError(String text, Object[] args) {
254-
255-
String formattedArgs = IntStream.range(0, args.length)
256-
.mapToObj(i -> (args[i] != null ?
257-
"[" + i + "] [type=" + args[i].getClass().getName() + "] [value=" + args[i] + "]" :
258-
"[" + i + "] [null]"))
259-
.collect(Collectors.joining(",\n", " ", " "));
260-
261-
return text + "\n" +
262-
"Controller [" + getBeanType().getName() + "]\n" +
263-
"Method [" + getBridgedMethod().toGenericString() + "] " +
264-
"with argument values:\n" + formattedArgs;
265-
}
266-
267214
}

0 commit comments

Comments
 (0)