From 260bbe319dfbe362ade0180f9c50a35109d992c8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 18 Dec 2013 18:08:32 +0100 Subject: [PATCH] Fixed accidental use of Java 8 getParameterCount(), plus polishing of related classes Issue: SPR-11245 --- ...tractNamedValueMethodArgumentResolver.java | 21 +++-- .../RequestParamMethodArgumentResolver.java | 55 ++++++------ .../CompositeUriComponentsContributor.java | 50 +++++++---- .../annotation/MvcUriComponentsBuilder.java | 86 ++++++++----------- .../PathVariableMethodArgumentResolver.java | 11 +-- 5 files changed, 114 insertions(+), 109 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java index e8d6fba1d6b..0675ecea78b 100644 --- a/spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java +++ b/spring-web/src/main/java/org/springframework/web/method/annotation/AbstractNamedValueMethodArgumentResolver.java @@ -18,7 +18,6 @@ package org.springframework.web.method.annotation; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; - import javax.servlet.ServletException; import org.springframework.beans.factory.config.BeanExpressionContext; @@ -61,8 +60,13 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle private final BeanExpressionContext expressionContext; - private Map namedValueInfoCache = - new ConcurrentHashMap(256); + private Map namedValueInfoCache = new ConcurrentHashMap(256); + + + public AbstractNamedValueMethodArgumentResolver() { + this.configurableBeanFactory = null; + this.expressionContext = null; + } /** * @param beanFactory a bean factory to use for resolving ${...} placeholder @@ -71,14 +75,13 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle */ public AbstractNamedValueMethodArgumentResolver(ConfigurableBeanFactory beanFactory) { this.configurableBeanFactory = beanFactory; - this.expressionContext = (beanFactory != null) ? new BeanExpressionContext(beanFactory, new RequestScope()) : null; + this.expressionContext = (beanFactory != null ? new BeanExpressionContext(beanFactory, new RequestScope()) : null); } + @Override - public final Object resolveArgument( - MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) - throws Exception { + public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { Class paramType = parameter.getParameterType(); NamedValueInfo namedValueInfo = getNamedValueInfo(parameter); @@ -217,7 +220,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle private final String defaultValue; - protected NamedValueInfo(String name, boolean required, String defaultValue) { + public NamedValueInfo(String name, boolean required, String defaultValue) { this.name = name; this.required = required; this.defaultValue = defaultValue; diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java index 3b34f3bc0ae..3b49c17743b 100644 --- a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java +++ b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -80,35 +79,45 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod private final boolean useDefaultResolution; + + /** + * @param useDefaultResolution in default resolution mode a method argument + * that is a simple type, as defined in {@link BeanUtils#isSimpleProperty}, + * is treated as a request parameter even if it it isn't annotated, the + * request parameter name is derived from the method parameter name. + */ + public RequestParamMethodArgumentResolver(boolean useDefaultResolution) { + this.useDefaultResolution = useDefaultResolution; + } + /** * @param beanFactory a bean factory used for resolving ${...} placeholder * and #{...} SpEL expressions in default values, or {@code null} if default * values are not expected to contain expressions * @param useDefaultResolution in default resolution mode a method argument * that is a simple type, as defined in {@link BeanUtils#isSimpleProperty}, - * is treated as a request parameter even if it itsn't annotated, the + * is treated as a request parameter even if it it isn't annotated, the * request parameter name is derived from the method parameter name. */ - public RequestParamMethodArgumentResolver(ConfigurableBeanFactory beanFactory, - boolean useDefaultResolution) { - + public RequestParamMethodArgumentResolver(ConfigurableBeanFactory beanFactory, boolean useDefaultResolution) { super(beanFactory); this.useDefaultResolution = useDefaultResolution; } + /** * Supports the following: *
    - *
  • @RequestParam-annotated method arguments. - * This excludes {@link Map} params where the annotation doesn't - * specify a name. See {@link RequestParamMapMethodArgumentResolver} - * instead for such params. - *
  • Arguments of type {@link MultipartFile} - * unless annotated with @{@link RequestPart}. - *
  • Arguments of type {@code javax.servlet.http.Part} - * unless annotated with @{@link RequestPart}. - *
  • In default resolution mode, simple type arguments - * even if not with @{@link RequestParam}. + *
  • @RequestParam-annotated method arguments. + * This excludes {@link Map} params where the annotation doesn't + * specify a name. See {@link RequestParamMapMethodArgumentResolver} + * instead for such params. + *
  • Arguments of type {@link MultipartFile} + * unless annotated with @{@link RequestPart}. + *
  • Arguments of type {@code javax.servlet.http.Part} + * unless annotated with @{@link RequestPart}. + *
  • In default resolution mode, simple type arguments + * even if not with @{@link RequestParam}. *
*/ @Override @@ -149,7 +158,6 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod @Override protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception { - Object arg; HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); @@ -243,9 +251,9 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod builder.queryParam(name); } else if (value instanceof Collection) { - for (Object v : (Collection) value) { - v = formatUriValue(conversionService, TypeDescriptor.nested(parameter, 1), v); - builder.queryParam(name, v); + for (Object element : (Collection) value) { + element = formatUriValue(conversionService, TypeDescriptor.nested(parameter, 1), element); + builder.queryParam(name, element); } } else { @@ -254,18 +262,17 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod } protected String formatUriValue(ConversionService cs, TypeDescriptor sourceType, Object value) { - return (cs != null) ? - (String) cs.convert(value, sourceType, STRING_TYPE_DESCRIPTOR) : null; + return (cs != null ? (String) cs.convert(value, sourceType, STRING_TYPE_DESCRIPTOR) : null); } - private class RequestParamNamedValueInfo extends NamedValueInfo { + private static class RequestParamNamedValueInfo extends NamedValueInfo { - private RequestParamNamedValueInfo() { + public RequestParamNamedValueInfo() { super("", false, ValueConstants.DEFAULT_NONE); } - private RequestParamNamedValueInfo(RequestParam annotation) { + public RequestParamNamedValueInfo(RequestParam annotation) { super(annotation.value(), annotation.required(), annotation.defaultValue()); } } diff --git a/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java b/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java index 11e890bd9a9..640172797f0 100644 --- a/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java +++ b/spring-web/src/main/java/org/springframework/web/method/support/CompositeUriComponentsContributor.java @@ -16,17 +16,18 @@ package org.springframework.web.method.support; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionService; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.util.Assert; import org.springframework.web.util.UriComponentsBuilder; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - /** * A {@link UriComponentsContributor} containing a list of other contributors * to delegate and also encapsulating a specific {@link ConversionService} to @@ -37,7 +38,7 @@ import java.util.Map; */ public class CompositeUriComponentsContributor implements UriComponentsContributor { - private final List contributors = new ArrayList(); + private final List contributors = new LinkedList(); private final ConversionService conversionService; @@ -46,10 +47,24 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut * Create an instance from a collection of {@link UriComponentsContributor}s or * {@link HandlerMethodArgumentResolver}s. Since both of these tend to be implemented * by the same class, the most convenient option is to obtain the configured - * {@code HandlerMethodArgumentResolvers} in {@code RequestMappingHandlerAdapter} and - * provide that to this constructor. + * {@code HandlerMethodArgumentResolvers} in {@code RequestMappingHandlerAdapter} + * and provide that to this constructor. * @param contributors a collection of {@link UriComponentsContributor} - * or {@link HandlerMethodArgumentResolver}s. + * or {@link HandlerMethodArgumentResolver}s. + */ + public CompositeUriComponentsContributor(UriComponentsContributor... contributors) { + Collections.addAll(this.contributors, contributors); + this.conversionService = new DefaultFormattingConversionService(); + } + + /** + * Create an instance from a collection of {@link UriComponentsContributor}s or + * {@link HandlerMethodArgumentResolver}s. Since both of these tend to be implemented + * by the same class, the most convenient option is to obtain the configured + * {@code HandlerMethodArgumentResolvers} in {@code RequestMappingHandlerAdapter} + * and provide that to this constructor. + * @param contributors a collection of {@link UriComponentsContributor} + * or {@link HandlerMethodArgumentResolver}s. */ public CompositeUriComponentsContributor(Collection contributors) { this(contributors, null); @@ -70,17 +85,14 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut * need to be formatted as Strings before being added to the URI */ public CompositeUriComponentsContributor(Collection contributors, ConversionService conversionService) { - Assert.notNull(contributors, "'uriComponentsContributors' must not be null"); - for (Object contributor : contributors) { if (contributor instanceof UriComponentsContributor) { this.contributors.add((UriComponentsContributor) contributor); } } - - this.conversionService = (conversionService != null) ? - conversionService : new DefaultFormattingConversionService(); + this.conversionService = + (conversionService != null ? conversionService : new DefaultFormattingConversionService()); } @@ -90,8 +102,8 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut @Override public boolean supportsParameter(MethodParameter parameter) { - for (UriComponentsContributor c : this.contributors) { - if (c.supportsParameter(parameter)) { + for (UriComponentsContributor contributor : this.contributors) { + if (contributor.supportsParameter(parameter)) { return true; } } @@ -102,9 +114,9 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut public void contributeMethodArgument(MethodParameter parameter, Object value, UriComponentsBuilder builder, Map uriVariables, ConversionService conversionService) { - for (UriComponentsContributor c : this.contributors) { - if (c.supportsParameter(parameter)) { - c.contributeMethodArgument(parameter, value, builder, uriVariables, conversionService); + for (UriComponentsContributor contributor : this.contributors) { + if (contributor.supportsParameter(parameter)) { + contributor.contributeMethodArgument(parameter, value, builder, uriVariables, conversionService); break; } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java index 26a940a87cd..0384261b827 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java @@ -16,9 +16,16 @@ package org.springframework.web.servlet.mvc.method.annotation; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + import org.aopalliance.intercept.MethodInterceptor; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.target.EmptyTargetSource; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -31,7 +38,12 @@ import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.objenesis.ObjenesisStd; -import org.springframework.util.*; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; +import org.springframework.util.PathMatcher; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.request.RequestAttributes; @@ -44,17 +56,12 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; -import javax.servlet.http.HttpServletRequest; -import java.lang.reflect.Method; -import java.util.*; - /** - * A UriComponentsBuilder that helps to build URIs to Spring MVC controllers and methods from their - * request mappings. + * A UriComponentsBuilder that helps to build URIs to Spring MVC controllers + * and methods from their request mappings. * * @author Oliver Gierke * @author Rossen Stoyanchev - * * @since 4.0 */ public class MvcUriComponentsBuilder extends UriComponentsBuilder { @@ -71,16 +78,14 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); - private final static ObjenesisStd objenesis = new ObjenesisStd(true); + private static final ObjenesisStd objenesis = new ObjenesisStd(true); - private static Log logger = LogFactory.getLog(MvcUriComponentsBuilder.class); + private static final Log logger = LogFactory.getLog(MvcUriComponentsBuilder.class); static { defaultUriComponentsContributor = new CompositeUriComponentsContributor( - Arrays. asList( - new PathVariableMethodArgumentResolver(), - new RequestParamMethodArgumentResolver(null, false))); + new PathVariableMethodArgumentResolver(), new RequestParamMethodArgumentResolver(false)); } @@ -113,23 +118,20 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { * @param argumentValues argument values matching to method parameters * @return a UriComponentsBuilder instance */ - public static UriComponentsBuilder fromMethodName(Class controllerType, - String methodName, Object... argumentValues) { - + public static UriComponentsBuilder fromMethodName(Class controllerType, String methodName, Object... argumentValues) { Method match = null; for (Method method : controllerType.getDeclaredMethods()) { - if ((method.getParameterCount() == argumentValues.length) && method.getName().equals(methodName)) { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argumentValues.length) { if (match != null) { - throw new IllegalStateException("Found two methods named '" + methodName - + "' having " + argumentValues + " arguments, controller " - + controllerType.getName()); + throw new IllegalStateException("Found two methods named '" + methodName + "' having " + + Arrays.asList(argumentValues) + " arguments, controller " + controllerType.getName()); } match = method; } } if (match == null) { - throw new IllegalArgumentException("No method '" + methodName + "' with " - + argumentValues.length + " parameters found in " + controllerType.getName()); + throw new IllegalArgumentException("No method '" + methodName + "' with " + argumentValues.length + + " parameters found in " + controllerType.getName()); } return fromMethod(match, argumentValues); } @@ -147,7 +149,6 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { * @return a UriComponentsBuilder instance */ public static UriComponentsBuilder fromMethod(Method method, Object... argumentValues) { - UriComponentsBuilder builder = ServletUriComponentsBuilder.newInstance().path(getMethodRequestMapping(method)); UriComponents uriComponents = applyContributors(builder, method, argumentValues); @@ -155,15 +156,13 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { String methodPath = uriComponents.getPath(); String path = pathMatcher.combine(typePath, methodPath); - return ServletUriComponentsBuilder.fromCurrentServletMapping().path( - path).queryParams(uriComponents.getQueryParams()); + return ServletUriComponentsBuilder.fromCurrentServletMapping().path(path).queryParams(uriComponents.getQueryParams()); } /** * Create a {@link UriComponents} by invoking a method on a "mock" controller, similar * to how test frameworks provide mock objects and record method invocations. *

For example given this controller: - * *

 	 * @RequestMapping("/people/{id}/addresses")
 	 * class AddressController {
@@ -175,11 +174,8 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 	 *   public void addAddress(Address address) { ... }
 	 * }
 	 * 
- * * A "mock" controller can be used as follows: - * - *
-	 *
+	 * 
 	 * // Inline style with static import of MvcUriComponentsBuilder.mock
 	 *
 	 * MvcUriComponentsBuilder.fromMethodCall(
@@ -191,9 +187,7 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 	 * controller.addAddress(null);
 	 *
 	 * MvcUriComponentsBuilder.fromMethodCall(controller);
-	 *
 	 * 
- * * The above supports {@code @PathVariable} and {@code @RequestParam} method parameters. * Any other arguments can be provided as {@literal null} and will be ignored. *

Additional (custom) argument types can be supported through an implementation @@ -203,7 +197,6 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { * @return a UriComponents instance */ public static UriComponentsBuilder fromMethodCall(Object methodInvocationInfo) { - Assert.isInstanceOf(MethodInvocationInfo.class, methodInvocationInfo); MethodInvocationInfo info = (MethodInvocationInfo) methodInvocationInfo; @@ -217,8 +210,7 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { String methodMapping = uriComponents.getPath(); String path = pathMatcher.combine(typeMapping, methodMapping); - return ServletUriComponentsBuilder.fromCurrentServletMapping().path( - path).queryParams(uriComponents.getQueryParams()); + return ServletUriComponentsBuilder.fromCurrentServletMapping().path(path).queryParams(uriComponents.getQueryParams()); } @@ -247,7 +239,6 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { } private static UriComponents applyContributors(UriComponentsBuilder builder, Method method, Object[] args) { - CompositeUriComponentsContributor contributor = getConfiguredUriComponentsContributor(); if (contributor == null) { logger.debug("Using default CompositeUriComponentsContributor"); @@ -256,18 +247,15 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { int paramCount = method.getParameterTypes().length; int argCount = args.length; - Assert.isTrue(paramCount == argCount, "Number of method parameters " + paramCount + " does not match number of argument values " + argCount); Map uriVars = new HashMap(); - for (int i=0; i < paramCount; i++) { MethodParameter param = new MethodParameter(method, i); param.initParameterNameDiscovery(parameterNameDiscoverer); contributor.contributeMethodArgument(param, args[i], builder, uriVars); } - return builder.buildAndExpand(uriVars); } @@ -294,8 +282,8 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { } catch (NoSuchBeanDefinitionException ex) { if (logger.isDebugEnabled()) { - logger.debug("No CompositeUriComponentsContributor bean with name '" - + MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME + "'"); + logger.debug("No CompositeUriComponentsContributor bean with name '" + + MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME + "'"); } return null; } @@ -308,7 +296,7 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { * {@link #fromMethodCall(Object)}. *

This is a shorthand version of {@link #controller(Class)} intended for * inline use as follows: - *

+	 * 
 	 * UriComponentsBuilder builder = MvcUriComponentsBuilder.fromMethodCall(
 	 * 		on(FooController.class).getFoo(1)).build();
 	 * 
@@ -325,7 +313,7 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder { * {@link #fromMethodCall(Object)}. *

This is a longer version of {@link #on(Class)} for use with void controller * methods as well as for creating multiple links in succession. - *

+	 * 
 	 * FooController fooController = controller(FooController.class);
 	 *
 	 * fooController.saveFoo(1, null);
@@ -343,7 +331,6 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 
 	@SuppressWarnings("unchecked")
 	private static  T initProxy(Class type, ControllerMethodInvocationInterceptor interceptor) {
-
 		if (type.isInterface()) {
 			ProxyFactory factory = new ProxyFactory(EmptyTargetSource.INSTANCE);
 			factory.addInterface(type);
@@ -356,9 +343,8 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 			enhancer.setSuperclass(type);
 			enhancer.setInterfaces(new Class[]{MethodInvocationInfo.class});
 			enhancer.setCallbackType(org.springframework.cglib.proxy.MethodInterceptor.class);
-
 			Factory factory = (Factory) objenesis.newInstance(enhancer.createClass());
-			factory.setCallbacks(new Callback[] { interceptor });
+			factory.setCallbacks(new Callback[] {interceptor});
 			return (T) factory;
 		}
 	}
@@ -373,15 +359,12 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 		private static final Method getArgumentValues =
 				ReflectionUtils.findMethod(MethodInvocationInfo.class, "getArgumentValues");
 
-
 		private Method controllerMethod;
 
 		private Object[] argumentValues;
 
-
 		@Override
 		public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) {
-
 			if (getControllerMethod.equals(method)) {
 				return this.controllerMethod;
 			}
@@ -394,9 +377,8 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 			else {
 				this.controllerMethod = method;
 				this.argumentValues = args;
-
 				Class returnType = method.getReturnType();
-				return void.class.equals(returnType) ? null : returnType.cast(initProxy(returnType, this));
+				return (void.class.equals(returnType) ? null : returnType.cast(initProxy(returnType, this)));
 			}
 		}
 
@@ -406,12 +388,12 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
 		}
 	}
 
+
 	public interface MethodInvocationInfo {
 
 		Method getControllerMethod();
 
 		Object[] getArgumentValues();
-
 	}
 
 }
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java
index 8cdac3db14f..f6ed15f3c4e 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/PathVariableMethodArgumentResolver.java
@@ -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");
  * you may not use this file except in compliance with the License.
@@ -56,8 +56,8 @@ import org.springframework.web.util.UriComponentsBuilder;
  * {@link RequestParamMapMethodArgumentResolver} is used instead to provide
  * access to all URI variables in a map.
  *
- * 

A {@link WebDataBinder} is invoked to apply type conversion to resolved path variable values that - * don't yet match the method parameter type. + *

A {@link WebDataBinder} is invoked to apply type conversion to resolved + * path variable values that don't yet match the method parameter type. * * @author Rossen Stoyanchev * @author Arjen Poutsma @@ -70,9 +70,9 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod public PathVariableMethodArgumentResolver() { - super(null); } + @Override public boolean supportsParameter(MethodParameter parameter) { if (!parameter.hasParameterAnnotation(PathVariable.class)) { @@ -143,8 +143,9 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod private static class PathVariableNamedValueInfo extends NamedValueInfo { - private PathVariableNamedValueInfo(PathVariable annotation) { + public PathVariableNamedValueInfo(PathVariable annotation) { super(annotation.value(), true, ValueConstants.DEFAULT_NONE); } } + }