Consistency between InvocableHandlerMethod in web and messaging modules

This commit is contained in:
Juergen Hoeller 2013-10-15 15:03:44 +02:00 committed by unknown
parent c38bde259a
commit 187b681b9e
2 changed files with 36 additions and 56 deletions

View File

@ -20,8 +20,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
@ -41,7 +41,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private HandlerMethodArgumentResolverComposite argumentResolvers = new HandlerMethodArgumentResolverComposite(); private HandlerMethodArgumentResolverComposite argumentResolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
/** /**
@ -59,20 +59,17 @@ public class InvocableHandlerMethod extends HandlerMethod {
} }
/** /**
* Constructs a new handler method with the given bean instance, method name and * Construct a new handler method with the given bean instance, method name and parameters.
* parameters.
*
* @param bean the object bean * @param bean the object bean
* @param methodName the method name * @param methodName the method name
* @param parameterTypes the method parameter types * @param parameterTypes the method parameter types
* @throws NoSuchMethodException when the method cannot be found * @throws NoSuchMethodException when the method cannot be found
*/ */
public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
throws NoSuchMethodException {
super(bean, methodName, parameterTypes); super(bean, methodName, parameterTypes);
} }
/** /**
* Set {@link HandlerMethodArgumentResolver}s to use to use for resolving method * Set {@link HandlerMethodArgumentResolver}s to use to use for resolving method
* argument values. * argument values.
@ -82,41 +79,33 @@ public class InvocableHandlerMethod extends HandlerMethod {
} }
/** /**
* Set the ParameterNameDiscoverer for resolving parameter names when needed (e.g. * Set the ParameterNameDiscoverer for resolving parameter names when needed
* default request attribute name). * (e.g. default request attribute name).
* <p> * <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
* Default is an
* {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}
* instance.
*/ */
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer; this.parameterNameDiscoverer = parameterNameDiscoverer;
} }
/** /**
* Invoke the method with the given message. * Invoke the method with the given message.
* * @throws Exception raised if no suitable argument resolver can be found,
* @exception Exception raised if no suitable argument resolver can be found, or the * or the method raised an exception
* method raised an exception
*/ */
public final Object invoke(Message<?> message, Object... providedArgs) throws Exception { public final Object invoke(Message<?> message, Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(message, providedArgs); Object[] args = getMethodArgumentValues(message, providedArgs);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
StringBuilder sb = new StringBuilder("Invoking ["); StringBuilder sb = new StringBuilder("Invoking [");
sb.append(this.getBeanType().getSimpleName()).append("."); sb.append(this.getBeanType().getSimpleName()).append(".");
sb.append(this.getMethod().getName()).append("] method with arguments "); sb.append(getMethod().getName()).append("] method with arguments ");
sb.append(Arrays.asList(args)); sb.append(Arrays.asList(args));
logger.trace(sb.toString()); logger.trace(sb.toString());
} }
Object returnValue = invoke(args); Object returnValue = invoke(args);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Method returned [" + returnValue + "]"); logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
} }
return returnValue; return returnValue;
} }
@ -124,31 +113,28 @@ public class InvocableHandlerMethod extends HandlerMethod {
* Get the method argument values for the current request. * Get the method argument values for the current request.
*/ */
private Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception { private Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters(); MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length]; Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) { for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i]; MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(parameterNameDiscoverer); parameter.initParameterNameDiscovery(parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(parameter, getBean().getClass()); GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
args[i] = resolveProvidedArgument(parameter, providedArgs); args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) { if (args[i] != null) {
continue; continue;
} }
if (this.argumentResolvers.supportsParameter(parameter)) { if (this.argumentResolvers.supportsParameter(parameter)) {
try { try {
args[i] = this.argumentResolvers.resolveArgument(parameter, message); args[i] = this.argumentResolvers.resolveArgument(parameter, message);
continue; continue;
} catch (Exception ex) { }
catch (Exception ex) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex); logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
} }
throw ex; throw ex;
} }
} }
if (args[i] == null) { if (args[i] == null) {
String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i); String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
throw new IllegalStateException(msg); throw new IllegalStateException(msg);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2013 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -69,19 +69,19 @@ public class InvocableHandlerMethod extends HandlerMethod {
} }
/** /**
* Constructs a new handler method with the given bean instance, method name and parameters. * Construct a new handler method with the given bean instance, method name and parameters.
* @param bean the object bean * @param bean the object bean
* @param methodName the method name * @param methodName the method name
* @param parameterTypes the method parameter types * @param parameterTypes the method parameter types
* @throws NoSuchMethodException when the method cannot be found * @throws NoSuchMethodException when the method cannot be found
*/ */
public InvocableHandlerMethod( public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
Object bean, String methodName, Class<?>... parameterTypes) throws NoSuchMethodException {
super(bean, methodName, parameterTypes); super(bean, methodName, parameterTypes);
} }
/** /**
* Sets the {@link WebDataBinderFactory} to be passed to argument resolvers allowing them to create * Set the {@link WebDataBinderFactory} to be passed to argument resolvers allowing them to create
* a {@link WebDataBinder} for data binding and type conversion purposes. * a {@link WebDataBinder} for data binding and type conversion purposes.
* @param dataBinderFactory the data binder factory. * @param dataBinderFactory the data binder factory.
*/ */
@ -105,71 +105,65 @@ public class InvocableHandlerMethod extends HandlerMethod {
this.parameterNameDiscoverer = parameterNameDiscoverer; this.parameterNameDiscoverer = parameterNameDiscoverer;
} }
/** /**
* Invoke the method after resolving its argument values in the context of the given request. <p>Argument * Invoke the method after resolving its argument values in the context of the given request. <p>Argument
* values are commonly resolved through {@link HandlerMethodArgumentResolver}s. The {@code provideArgs} * values are commonly resolved through {@link HandlerMethodArgumentResolver}s. The {@code provideArgs}
* parameter however may supply argument values to be used directly, i.e. without argument resolution. * parameter however may supply argument values to be used directly, i.e. without argument resolution.
* Examples of provided argument values include a {@link WebDataBinder}, a {@link SessionStatus}, or * Examples of provided argument values include a {@link WebDataBinder}, a {@link SessionStatus}, or
* a thrown exception instance. Provided argument values are checked before argument resolvers. * a thrown exception instance. Provided argument values are checked before argument resolvers.
*
* @param request the current request * @param request the current request
* @param mavContainer the ModelAndViewContainer for this request * @param mavContainer the ModelAndViewContainer for this request
* @param providedArgs "given" arguments matched by type, not resolved * @param providedArgs "given" arguments matched by type, not resolved
* @return the raw value returned by the invoked method * @return the raw value returned by the invoked method
* @exception Exception raised if no suitable argument resolver can be found, or the method raised an exception * @exception Exception raised if no suitable argument resolver can be found, or the method raised an exception
*/ */
public final Object invokeForRequest(NativeWebRequest request, public final Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
Object... providedArgs) throws Exception {
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
StringBuilder builder = new StringBuilder("Invoking ["); StringBuilder sb = new StringBuilder("Invoking [");
builder.append(this.getMethod().getName()).append("] method with arguments "); sb.append(this.getBeanType().getSimpleName()).append(".");
builder.append(Arrays.asList(args)); sb.append(getMethod().getName()).append("] method with arguments ");
logger.trace(builder.toString()); sb.append(Arrays.asList(args));
logger.trace(sb.toString());
} }
Object returnValue = invoke(args); Object returnValue = invoke(args);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Method [" + this.getMethod().getName() + "] returned [" + returnValue + "]"); logger.trace("Method [" + getMethod().getName() + "] returned [" + returnValue + "]");
} }
return returnValue; return returnValue;
} }
/** /**
* Get the method argument values for the current request. * Get the method argument values for the current request.
*/ */
private Object[] getMethodArgumentValues( private Object[] getMethodArgumentValues(NativeWebRequest request, ModelAndViewContainer mavContainer,
NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception { Object... providedArgs) throws Exception {
MethodParameter[] parameters = getMethodParameters(); MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length]; Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) { for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i]; MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(parameterNameDiscoverer); parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(parameter, getBean().getClass()); GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
args[i] = resolveProvidedArgument(parameter, providedArgs); args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) { if (args[i] != null) {
continue; continue;
} }
if (this.argumentResolvers.supportsParameter(parameter)) {
if (argumentResolvers.supportsParameter(parameter)) {
try { try {
args[i] = argumentResolvers.resolveArgument(parameter, mavContainer, request, dataBinderFactory); args[i] = this.argumentResolvers.resolveArgument(parameter, mavContainer, request, this.dataBinderFactory);
continue; continue;
} catch (Exception ex) { }
catch (Exception ex) {
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex); logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
} }
throw ex; throw ex;
} }
} }
if (args[i] == null) { if (args[i] == null) {
String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i); String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
throw new IllegalStateException(msg); throw new IllegalStateException(msg);