Configurable arg resolvers and return value handlers

This commit is contained in:
Rossen Stoyanchev
2011-04-06 16:55:21 +00:00
parent ca9a3b4584
commit ffec444434
13 changed files with 224 additions and 113 deletions

View File

@@ -37,14 +37,14 @@ import org.springframework.web.context.request.NativeWebRequest;
* @author Rossen Stoyanchev
* @since 3.1
*/
public class HandlerMethodArgumentResolverContainer implements HandlerMethodArgumentResolver {
public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgumentResolver {
protected final Log logger = LogFactory.getLog(HandlerMethodArgumentResolverContainer.class);
protected final Log logger = LogFactory.getLog(HandlerMethodArgumentResolverComposite.class);
private List<HandlerMethodArgumentResolver> argumentResolvers =
private final List<HandlerMethodArgumentResolver> argumentResolvers =
new ArrayList<HandlerMethodArgumentResolver>();
private Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
new ConcurrentHashMap<MethodParameter, HandlerMethodArgumentResolver>();
/**

View File

@@ -35,14 +35,14 @@ import org.springframework.web.context.request.NativeWebRequest;
* @author Rossen Stoyanchev
* @since 3.1
*/
public class HandlerMethodReturnValueHandlerContainer implements HandlerMethodReturnValueHandler {
public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {
protected final Log logger = LogFactory.getLog(HandlerMethodArgumentResolverContainer.class);
protected final Log logger = LogFactory.getLog(HandlerMethodArgumentResolverComposite.class);
private List<HandlerMethodReturnValueHandler> returnValueHandlers =
private final List<HandlerMethodReturnValueHandler> returnValueHandlers =
new ArrayList<HandlerMethodReturnValueHandler>();
private Map<MethodParameter, HandlerMethodReturnValueHandler> returnValueHandlerCache =
private final Map<MethodParameter, HandlerMethodReturnValueHandler> returnValueHandlerCache =
new ConcurrentHashMap<MethodParameter, HandlerMethodReturnValueHandler>();
/**

View File

@@ -16,7 +16,6 @@
package org.springframework.web.method.support;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
@@ -39,14 +38,14 @@ import org.springframework.web.method.HandlerMethod;
*
* <p>Resolving argument values often requires a {@link WebDataBinder} for data binding and type conversion.
* Use {@link #setDataBinderFactory(WebDataBinderFactory)} to provide a factory for that. The list of argument
* resolvers can be set via {@link #setArgumentResolverContainer(HandlerMethodArgumentResolverContainer)}.
* resolvers can be set via {@link #setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite)}.
*
* @author Rossen Stoyanchev
* @since 3.1
*/
public class InvocableHandlerMethod extends HandlerMethod {
private HandlerMethodArgumentResolverContainer argumentResolvers = new HandlerMethodArgumentResolverContainer();
private HandlerMethodArgumentResolverComposite argumentResolvers = new HandlerMethodArgumentResolverComposite();
private WebDataBinderFactory dataBinderFactory;
@@ -86,7 +85,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
/**
* Set {@link HandlerMethodArgumentResolver}s to use to use for resolving method argument values.
*/
public void setArgumentResolverContainer(HandlerMethodArgumentResolverContainer argumentResolvers) {
public void setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
this.argumentResolvers = argumentResolvers;
}
@@ -102,7 +101,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
/**
* Invoke the method after resolving its argument values based on the given request.
* <p>Most argument values are resolved with the help of {@link HandlerMethodArgumentResolver}s
* configured via {@link #setArgumentResolverContainer(HandlerMethodArgumentResolverContainer)}.
* configured via {@link #setHandlerMethodArgumentResolvers(HandlerMethodArgumentResolverComposite)}.
* However, the {@code provideArgs} parameter can be used to supply argument values for use
* directly rather than relying on argument resolution - e.g. {@link WebDataBinder},
* {@link SessionStatus}, or the thrown exception in a HandlerExceptionResolver.

View File

@@ -40,7 +40,7 @@ import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.annotation.support.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.InvocableHandlerMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolverContainer;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
/**
* Test fixture for {@link InitBinderMethodDataBinderFactory} unit tests.
@@ -109,7 +109,7 @@ public class InitBinderMethodDataBinderFactoryTests {
public void createBinderTypeConversion() throws Exception {
request.setParameter("requestParam", "22");
HandlerMethodArgumentResolverContainer argResolvers = new HandlerMethodArgumentResolverContainer();
HandlerMethodArgumentResolverComposite argResolvers = new HandlerMethodArgumentResolverComposite();
argResolvers.registerArgumentResolver(new RequestParamMethodArgumentResolver(null, false));
String methodName = "initBinderTypeConversion";
@@ -122,16 +122,16 @@ public class InitBinderMethodDataBinderFactoryTests {
private InitBinderMethodDataBinderFactory createFactory(String methodName, Class<?>... parameterTypes)
throws Exception {
return createFactory(new HandlerMethodArgumentResolverContainer(), methodName, parameterTypes);
return createFactory(new HandlerMethodArgumentResolverComposite(), methodName, parameterTypes);
}
private InitBinderMethodDataBinderFactory createFactory(HandlerMethodArgumentResolverContainer argResolvers,
private InitBinderMethodDataBinderFactory createFactory(HandlerMethodArgumentResolverComposite argResolvers,
String methodName, Class<?>... parameterTypes) throws Exception {
Object handler = new InitBinderHandler();
Method method = InitBinderHandler.class.getMethod(methodName, parameterTypes);
InvocableHandlerMethod controllerMethod = new InvocableHandlerMethod(handler, method);
controllerMethod.setArgumentResolverContainer(argResolvers);
controllerMethod.setHandlerMethodArgumentResolvers(argResolvers);
controllerMethod.setDataBinderFactory(new DefaultDataBinderFactory(null));
controllerMethod.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());

View File

@@ -46,7 +46,7 @@ import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.annotation.support.ModelMethodProcessor;
import org.springframework.web.method.support.HandlerMethodArgumentResolverContainer;
import org.springframework.web.method.support.HandlerMethodArgumentResolverComposite;
import org.springframework.web.method.support.InvocableHandlerMethod;
/**
@@ -154,11 +154,11 @@ public class ModelFactoryTests {
private ModelFactory createFactory(Object handler, String methodName, Class<?>... parameterTypes) throws Exception{
Method method = ModelHandler.class.getMethod(methodName, parameterTypes);
HandlerMethodArgumentResolverContainer argResolvers = new HandlerMethodArgumentResolverContainer();
HandlerMethodArgumentResolverComposite argResolvers = new HandlerMethodArgumentResolverComposite();
argResolvers.registerArgumentResolver(new ModelMethodProcessor());
InvocableHandlerMethod controllerMethod = new InvocableHandlerMethod(handler, method);
controllerMethod.setArgumentResolverContainer(argResolvers);
controllerMethod.setHandlerMethodArgumentResolvers(argResolvers);
controllerMethod.setDataBinderFactory(null);
controllerMethod.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());

View File

@@ -27,13 +27,13 @@ import org.junit.Test;
import org.springframework.core.MethodParameter;
/**
* Test fixture for {@link HandlerMethodArgumentResolverContainer} unit tests.
* Test fixture for {@link HandlerMethodArgumentResolverComposite} unit tests.
*
* @author Rossen Stoyanchev
*/
public class HandlerMethodArgumentResolverContainerTests {
public class HandlerMethodArgumentResolverCompositeTests {
private HandlerMethodArgumentResolverContainer container;
private HandlerMethodArgumentResolverComposite composite;
private MethodParameter paramInteger;
@@ -41,7 +41,7 @@ public class HandlerMethodArgumentResolverContainerTests {
@Before
public void setUp() throws Exception {
this.container = new HandlerMethodArgumentResolverContainer();
this.composite = new HandlerMethodArgumentResolverComposite();
Method method = getClass().getDeclaredMethod("handle", Integer.class, String.class);
this.paramInteger = new MethodParameter(method, 0);
@@ -52,14 +52,14 @@ public class HandlerMethodArgumentResolverContainerTests {
public void supportsParameter() throws Exception {
registerResolver(Integer.class, null, false);
assertTrue(this.container.supportsParameter(paramInteger));
assertFalse(this.container.supportsParameter(paramString));
assertTrue(this.composite.supportsParameter(paramInteger));
assertFalse(this.composite.supportsParameter(paramString));
}
@Test
public void resolveArgument() throws Exception {
registerResolver(Integer.class, Integer.valueOf(55), false);
Object resolvedValue = this.container.resolveArgument(paramInteger, null, null, null);
Object resolvedValue = this.composite.resolveArgument(paramInteger, null, null, null);
assertEquals(Integer.valueOf(55), resolvedValue);
}
@@ -68,31 +68,31 @@ public class HandlerMethodArgumentResolverContainerTests {
public void resolveArgumentMultipleResolvers() throws Exception {
registerResolver(Integer.class, Integer.valueOf(1), false);
registerResolver(Integer.class, Integer.valueOf(2), false);
Object resolvedValue = this.container.resolveArgument(paramInteger, null, null, null);
Object resolvedValue = this.composite.resolveArgument(paramInteger, null, null, null);
assertEquals("Didn't use the first registered resolver", Integer.valueOf(1), resolvedValue);
}
@Test(expected=IllegalStateException.class)
public void noSuitableArgumentResolver() throws Exception {
this.container.resolveArgument(paramString, null, null, null);
this.composite.resolveArgument(paramString, null, null, null);
}
@Test
public void argResolverUsesResponse() throws Exception {
registerResolver(Integer.class, null, true);
assertTrue(this.container.usesResponseArgument(paramInteger));
assertTrue(this.composite.usesResponseArgument(paramInteger));
}
@Test
public void argResolverDoesntUseResponse() throws Exception {
registerResolver(Integer.class, null, false);
assertFalse(this.container.usesResponseArgument(paramInteger));
assertFalse(this.composite.usesResponseArgument(paramInteger));
}
protected StubArgumentResolver registerResolver(Class<?> supportedType, Object stubValue, boolean usesResponse) {
StubArgumentResolver resolver = new StubArgumentResolver(supportedType, stubValue, usesResponse);
this.container.registerArgumentResolver(resolver);
this.composite.registerArgumentResolver(resolver);
return resolver;
}

View File

@@ -26,13 +26,13 @@ import org.junit.Test;
import org.springframework.core.MethodParameter;
/**
* Test fixture for {@link HandlerMethodReturnValueHandlerContainer} unit tests.
* Test fixture for {@link HandlerMethodReturnValueHandlerComposite} unit tests.
*
* @author Rossen Stoyanchev
*/
public class HandlerMethodReturnValueHandlerContainerTests {
public class HandlerMethodReturnValueHandlerCompositeTests {
private HandlerMethodReturnValueHandlerContainer container;
private HandlerMethodReturnValueHandlerComposite composite;
ModelAndViewContainer mavContainer;
@@ -42,7 +42,7 @@ public class HandlerMethodReturnValueHandlerContainerTests {
@Before
public void setUp() throws Exception {
this.container = new HandlerMethodReturnValueHandlerContainer();
this.composite = new HandlerMethodReturnValueHandlerComposite();
this.paramInteger = new MethodParameter(getClass().getDeclaredMethod("handleInteger"), -1);
this.paramString = new MethodParameter(getClass().getDeclaredMethod("handleString"), -1);
@@ -54,14 +54,14 @@ public class HandlerMethodReturnValueHandlerContainerTests {
public void supportsReturnType() throws Exception {
registerReturnValueHandler(Integer.class, false);
assertTrue(this.container.supportsReturnType(paramInteger));
assertFalse(this.container.supportsReturnType(paramString));
assertTrue(this.composite.supportsReturnType(paramInteger));
assertFalse(this.composite.supportsReturnType(paramString));
}
@Test
public void handleReturnValue() throws Exception {
StubReturnValueHandler handler = registerReturnValueHandler(Integer.class, false);
this.container.handleReturnValue(Integer.valueOf(55), paramInteger, mavContainer, null);
this.composite.handleReturnValue(Integer.valueOf(55), paramInteger, mavContainer, null);
assertEquals(Integer.valueOf(55), handler.getUnhandledReturnValue());
}
@@ -70,7 +70,7 @@ public class HandlerMethodReturnValueHandlerContainerTests {
public void handleReturnValueMultipleHandlers() throws Exception {
StubReturnValueHandler handler1 = registerReturnValueHandler(Integer.class, false);
StubReturnValueHandler handler2 = registerReturnValueHandler(Integer.class, false);
this.container.handleReturnValue(Integer.valueOf(55), paramInteger, mavContainer, null);
this.composite.handleReturnValue(Integer.valueOf(55), paramInteger, mavContainer, null);
assertEquals("Didn't use the 1st registered handler", Integer.valueOf(55), handler1.getUnhandledReturnValue());
assertNull("Shouldn't have use the 2nd registered handler", handler2.getUnhandledReturnValue());
@@ -79,24 +79,24 @@ public class HandlerMethodReturnValueHandlerContainerTests {
@Test(expected=IllegalStateException.class)
public void noSuitableReturnValueHandler() throws Exception {
registerReturnValueHandler(Integer.class, false);
this.container.handleReturnValue("value", paramString, null, null);
this.composite.handleReturnValue("value", paramString, null, null);
}
@Test
public void returnValueHandlerUsesResponse() throws Exception {
registerReturnValueHandler(Integer.class, true);
assertTrue(this.container.usesResponseArgument(paramInteger));
assertTrue(this.composite.usesResponseArgument(paramInteger));
}
@Test
public void returnValueHandlerDosntUseResponse() throws Exception {
registerReturnValueHandler(Integer.class, false);
assertFalse(this.container.usesResponseArgument(paramInteger));
assertFalse(this.composite.usesResponseArgument(paramInteger));
}
protected StubReturnValueHandler registerReturnValueHandler(Class<?> returnType, boolean usesResponse) {
StubReturnValueHandler handler = new StubReturnValueHandler(returnType, usesResponse);
this.container.registerReturnValueHandler(handler);
this.composite.registerReturnValueHandler(handler);
return handler;
}

View File

@@ -38,7 +38,7 @@ import org.springframework.web.context.request.ServletWebRequest;
*/
public class InvocableHandlerMethodTests {
private HandlerMethodArgumentResolverContainer argResolvers;
private HandlerMethodArgumentResolverComposite argResolvers;
private NativeWebRequest webRequest;
@@ -46,7 +46,7 @@ public class InvocableHandlerMethodTests {
@Before
public void setUp() throws Exception {
argResolvers = new HandlerMethodArgumentResolverContainer();
argResolvers = new HandlerMethodArgumentResolverComposite();
response = new MockHttpServletResponse();
this.webRequest = new ServletWebRequest(new MockHttpServletRequest(), response);
@@ -96,7 +96,7 @@ public class InvocableHandlerMethodTests {
throws Exception {
Method method = handler.getClass().getDeclaredMethod(methodName, paramTypes);
InvocableHandlerMethod handlerMethod = new InvocableHandlerMethod(handler, method);
handlerMethod.setArgumentResolverContainer(argResolvers);
handlerMethod.setHandlerMethodArgumentResolvers(argResolvers);
return handlerMethod;
}