From dc1f921f5c357ed6593b3d99b22cb8f6d34849f2 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 30 Jun 2015 00:02:02 +0200 Subject: [PATCH] Split between basic MethodParameter and SynthesizingMethodParameter This split avoids a package tangle (between core and core.annotation) and also allows for selective use of raw annotation exposure versus synthesized annotations, with the latter primarily applicable to web and message handler processing at this point. Issue: SPR-13153 --- .../springframework/core/MethodParameter.java | 40 +++++- .../springframework/core/ResolvableType.java | 4 +- .../core/annotation/AnnotationUtils.java | 123 +++++++----------- .../SynthesizingMethodParameter.java | 59 +++++++++ .../messaging/handler/HandlerMethod.java | 3 +- .../HeaderMethodArgumentResolverTests.java | 12 +- .../support/PayloadArgumentResolverTests.java | 22 ++-- .../SendToMethodReturnValueHandlerTests.java | 27 ++-- .../support/HandlerMethodInvoker.java | 7 +- .../web/method/HandlerMethod.java | 3 +- .../RequestHeaderMethodArgumentResolver.java | 4 +- .../CompositeUriComponentsContributor.java | 16 +-- ...ookieValueMethodArgumentResolverTests.java | 12 +- ...tHeaderMapMethodArgumentResolverTests.java | 16 ++- ...uestHeaderMethodArgumentResolverTests.java | 16 ++- ...stParamMapMethodArgumentResolverTests.java | 16 ++- ...questParamMethodArgumentResolverTests.java | 38 +++--- ...otationMethodHandlerExceptionResolver.java | 5 +- ...otationMethodHandlerExceptionResolver.java | 5 +- .../annotation/MvcUriComponentsBuilder.java | 3 +- .../RequestPartMethodArgumentResolver.java | 1 - ...riablesMapMethodArgumentResolverTests.java | 20 ++- ...equestPartMethodArgumentResolverTests.java | 38 +++--- ...ookieValueMethodArgumentResolverTests.java | 12 +- 24 files changed, 286 insertions(+), 216 deletions(-) create mode 100644 spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java diff --git a/spring-core/src/main/java/org/springframework/core/MethodParameter.java b/spring-core/src/main/java/org/springframework/core/MethodParameter.java index 6a0137aa571..19c397e627b 100644 --- a/spring-core/src/main/java/org/springframework/core/MethodParameter.java +++ b/spring-core/src/main/java/org/springframework/core/MethodParameter.java @@ -26,7 +26,6 @@ import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; -import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; /** @@ -34,6 +33,10 @@ import org.springframework.util.Assert; * a Method or Constructor plus a parameter index and a nested type index for * a declared generic type. Useful as a specification object to pass along. * + *

As of 4.2, there is a {@link org.springframework.core.annotation.SynthesizingMethodParameter} + * subclass available which synthesizes annotations based on overridden annotation attributes. + * That subclass is being used for web and message endpoint processing, in particular. + * * @author Juergen Hoeller * @author Rob Harrop * @author Andy Clement @@ -388,7 +391,7 @@ public class MethodParameter { * Return the annotations associated with the target method/constructor itself. */ public Annotation[] getMethodAnnotations() { - return AnnotationUtils.synthesizeAnnotationArray(getAnnotatedElement().getAnnotations(), getAnnotatedElement()); + return adaptAnnotationArray(getAnnotatedElement().getAnnotations()); } /** @@ -396,9 +399,8 @@ public class MethodParameter { * @param annotationType the annotation type to look for * @return the annotation object, or {@code null} if not found */ - public T getMethodAnnotation(Class annotationType) { - AnnotatedElement element = getAnnotatedElement(); - return AnnotationUtils.synthesizeAnnotation(element.getAnnotation(annotationType), element); + public A getMethodAnnotation(Class annotationType) { + return adaptAnnotation(getAnnotatedElement().getAnnotation(annotationType)); } /** @@ -409,8 +411,7 @@ public class MethodParameter { Annotation[][] annotationArray = (this.method != null ? this.method.getParameterAnnotations() : this.constructor.getParameterAnnotations()); if (this.parameterIndex >= 0 && this.parameterIndex < annotationArray.length) { - this.parameterAnnotations = AnnotationUtils.synthesizeAnnotationArray( - annotationArray[this.parameterIndex], getAnnotatedElement()); + this.parameterAnnotations = adaptAnnotationArray(annotationArray[this.parameterIndex]); } else { this.parameterAnnotations = new Annotation[0]; @@ -480,6 +481,31 @@ public class MethodParameter { } + /** + * A template method to post-process a given annotation instance before + * returning it to the caller. + *

The default implementation simply returns the given annotation as-is. + * @param annotation the annotation about to be returned + * @return the post-processed annotation (or simply the original one) + * @since 4.2 + */ + protected A adaptAnnotation(A annotation) { + return annotation; + } + + /** + * A template method to post-process a given annotation array before + * returning it to the caller. + *

The default implementation simply returns the given annotation array as-is. + * @param annotations the annotation array about to be returned + * @return the post-processed annotation array (or simply the original one) + * @since 4.2 + */ + protected Annotation[] adaptAnnotationArray(Annotation[] annotations) { + return annotations; + } + + @Override public boolean equals(Object other) { if (this == other) { diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 8432d755692..d52cfa5498a 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -1122,7 +1122,7 @@ public class ResolvableType implements Serializable { */ public static ResolvableType forMethodReturnType(Method method) { Assert.notNull(method, "Method must not be null"); - return forMethodParameter(MethodParameter.forMethodOrConstructor(method, -1)); + return forMethodParameter(new MethodParameter(method, -1)); } /** @@ -1136,7 +1136,7 @@ public class ResolvableType implements Serializable { */ public static ResolvableType forMethodReturnType(Method method, Class implementationClass) { Assert.notNull(method, "Method must not be null"); - MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(method, -1); + MethodParameter methodParameter = new MethodParameter(method, -1); methodParameter.setContainingClass(implementationClass); return forMethodParameter(methodParameter); } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 030fc45268c..b42818a03d1 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -266,6 +266,7 @@ public abstract class AnnotationUtils { @Deprecated public static Set getRepeatableAnnotation(Method method, Class containerAnnotationType, Class annotationType) { + return getRepeatableAnnotations(method, annotationType, containerAnnotationType); } @@ -280,6 +281,7 @@ public abstract class AnnotationUtils { @Deprecated public static Set getRepeatableAnnotation(AnnotatedElement annotatedElement, Class containerAnnotationType, Class annotationType) { + return getRepeatableAnnotations(annotatedElement, annotationType, containerAnnotationType); } @@ -311,6 +313,7 @@ public abstract class AnnotationUtils { */ public static Set getRepeatableAnnotations(AnnotatedElement annotatedElement, Class annotationType) { + return getRepeatableAnnotations(annotatedElement, annotationType, null); } @@ -353,7 +356,7 @@ public abstract class AnnotationUtils { if (annotatedElement instanceof Class) { Class superclass = ((Class) annotatedElement).getSuperclass(); - if ((superclass != null) && (Object.class != superclass)) { + if (superclass != null && Object.class != superclass) { return getRepeatableAnnotations(superclass, annotationType, containerAnnotationType); } } @@ -434,7 +437,6 @@ public abstract class AnnotationUtils { * compiler if the supplied element is a {@link Method}. *

Meta-annotations will be searched if the annotation is not * present on the supplied element. - * * @param annotatedElement the element to look for annotations on; never {@code null} * @param annotationType the annotation type to look for; never {@code null} * @param containerAnnotationType the type of the container that holds @@ -955,10 +957,8 @@ public abstract class AnnotationUtils { /** * Retrieve the given annotation's attributes as an {@link AnnotationAttributes} map. - * *

This method provides fully recursive annotation reading capabilities on par with * the reflection-based {@link org.springframework.core.type.StandardAnnotationMetadata}. - * *

NOTE: This variant of {@code getAnnotationAttributes()} is * only intended for use within the framework. Specifically, the {@code mergeMode} flag * can be set to {@code true} in order to support processing of attribute aliases while @@ -975,7 +975,6 @@ public abstract class AnnotationUtils { * ensure that placeholders have been replaced by actual default values and * in order to enforce {@code @AliasFor} semantics. * - * * @param annotatedElement the element that is annotated with the supplied annotation; * may be {@code null} if unknown * @param annotation the annotation to retrieve the attributes for @@ -1062,8 +1061,7 @@ public abstract class AnnotationUtils { Annotation annotation = (Annotation) value; if (nestedAnnotationsAsMap) { - return getAnnotationAttributes(annotatedElement, annotation, classValuesAsString, - nestedAnnotationsAsMap); + return getAnnotationAttributes(annotatedElement, annotation, classValuesAsString, true); } else { return synthesizeAnnotation(annotation, annotatedElement); @@ -1077,7 +1075,7 @@ public abstract class AnnotationUtils { AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[annotations.length]; for (int i = 0; i < annotations.length; i++) { mappedAnnotations[i] = getAnnotationAttributes(annotatedElement, annotations[i], - classValuesAsString, nestedAnnotationsAsMap); + classValuesAsString, true); } return mappedAnnotations; } @@ -1183,7 +1181,6 @@ public abstract class AnnotationUtils { * by wrapping it in a dynamic proxy that transparently enforces * attribute alias semantics for annotation attributes that are * annotated with {@link AliasFor @AliasFor}. - * * @param annotation the annotation to synthesize * @return the synthesized annotation, if the supplied annotation is * synthesizable; {@code null} if the supplied annotation is @@ -1202,7 +1199,6 @@ public abstract class AnnotationUtils { * by wrapping it in a dynamic proxy that transparently enforces * attribute alias semantics for annotation attributes that are * annotated with {@link AliasFor @AliasFor}. - * * @param annotation the annotation to synthesize * @param annotatedElement the element that is annotated with the supplied * annotation; may be {@code null} if unknown @@ -1229,11 +1225,11 @@ public abstract class AnnotationUtils { return annotation; } - AnnotationAttributeExtractor attributeExtractor = new DefaultAnnotationAttributeExtractor(annotation, - annotatedElement); + AnnotationAttributeExtractor attributeExtractor = + new DefaultAnnotationAttributeExtractor(annotation, annotatedElement); InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); - A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), new Class[] { - (Class) annotationType, SynthesizedAnnotation.class }, handler); + A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), + new Class[] {(Class) annotationType, SynthesizedAnnotation.class}, handler); return synthesizedAnnotation; } @@ -1250,7 +1246,6 @@ public abstract class AnnotationUtils { *

Note that {@link AnnotationAttributes} is a specialized type of * {@link Map} that is an ideal candidate for this method's * {@code attributes} argument. - * * @param attributes the map of annotation attributes to synthesize * @param annotationType the type of annotation to synthesize; never {@code null} * @param annotatedElement the element that is annotated with the annotation @@ -1268,17 +1263,17 @@ public abstract class AnnotationUtils { @SuppressWarnings("unchecked") public static A synthesizeAnnotation(Map attributes, Class annotationType, AnnotatedElement annotatedElement) { - Assert.notNull(annotationType, "annotationType must not be null"); + Assert.notNull(annotationType, "annotationType must not be null"); if (attributes == null) { return null; } - AnnotationAttributeExtractor attributeExtractor = new MapAnnotationAttributeExtractor(attributes, - annotationType, annotatedElement); + AnnotationAttributeExtractor attributeExtractor = + new MapAnnotationAttributeExtractor(attributes, annotationType, annotatedElement); InvocationHandler handler = new SynthesizedAnnotationInvocationHandler(attributeExtractor); - A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), new Class[] { - annotationType, SynthesizedAnnotation.class }, handler); + A synthesizedAnnotation = (A) Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), + new Class[] {annotationType, SynthesizedAnnotation.class}, handler); return synthesizedAnnotation; } @@ -1289,7 +1284,6 @@ public abstract class AnnotationUtils { * {@link #synthesizeAnnotation(Map, Class, AnnotatedElement)}, * supplying an empty map for the source attribute values and {@code null} * for the {@link AnnotatedElement}. - * * @param annotationType the type of annotation to synthesize; never {@code null} * @return the synthesized annotation * @throws IllegalArgumentException if a required attribute is missing @@ -1308,7 +1302,6 @@ public abstract class AnnotationUtils { * creating a new array of the same size and type and populating it * with {@linkplain #synthesizeAnnotation(Annotation) synthesized} * versions of the annotations from the input array. - * * @param annotations the array of annotations to synthesize * @param annotatedElement the element that is annotated with the supplied * array of annotations; may be {@code null} if unknown @@ -1325,7 +1318,8 @@ public abstract class AnnotationUtils { return null; } - Annotation[] synthesized = (Annotation[]) Array.newInstance(annotations.getClass().getComponentType(), annotations.length); + Annotation[] synthesized = (Annotation[]) Array.newInstance( + annotations.getClass().getComponentType(), annotations.length); for (int i = 0; i < annotations.length; i++) { synthesized[i] = synthesizeAnnotation(annotations[i], annotatedElement); } @@ -1335,14 +1329,11 @@ public abstract class AnnotationUtils { /** * Get a map of all attribute alias pairs, declared via {@code @AliasFor} * in the supplied annotation type. - * *

The map is keyed by attribute name with each value representing * the name of the aliased attribute. For each entry {@code [x, y]} in * the map there will be a corresponding {@code [y, x]} entry in the map. - * *

An empty return value implies that the annotation does not declare * any attribute aliases. - * * @param annotationType the annotation type to find attribute aliases in * @return a map containing attribute alias pairs; never {@code null} * @since 4.2 @@ -1376,34 +1367,28 @@ public abstract class AnnotationUtils { * synthesizable (i.e., in need of being wrapped in a dynamic * proxy that provides functionality above that of a standard JDK * annotation). - * *

Specifically, an annotation is synthesizable if it declares * any attributes that are configured as aliased pairs via * {@link AliasFor @AliasFor} or if any nested annotations used by the * annotation declare such aliased pairs. - * * @since 4.2 * @see SynthesizedAnnotation * @see SynthesizedAnnotationInvocationHandler */ @SuppressWarnings("unchecked") private static boolean isSynthesizable(Class annotationType) { - Boolean synthesizable = synthesizableCache.get(annotationType); if (synthesizable != null) { return synthesizable.booleanValue(); } synthesizable = Boolean.FALSE; - for (Method attribute : getAttributeMethods(annotationType)) { if (getAliasedAttributeName(attribute) != null) { synthesizable = Boolean.TRUE; break; } - Class returnType = attribute.getReturnType(); - if (Annotation[].class.isAssignableFrom(returnType)) { Class nestedAnnotationType = (Class) returnType.getComponentType(); if (isSynthesizable(nestedAnnotationType)) { @@ -1421,20 +1406,17 @@ public abstract class AnnotationUtils { } synthesizableCache.put(annotationType, synthesizable); - return synthesizable.booleanValue(); } /** * Get the name of the aliased attribute configured via * {@link AliasFor @AliasFor} on the supplied annotation {@code attribute}. - * *

This method does not resolve aliases in other annotations. In * other words, if {@code @AliasFor} is present on the supplied * {@code attribute} but {@linkplain AliasFor#annotation references an * annotation} other than {@link Annotation}, this method will return * {@code null} immediately. - * * @param attribute the attribute to find an alias for * @return the name of the aliased attribute, or {@code null} if not found * @throws IllegalArgumentException if the supplied attribute method is @@ -1451,7 +1433,6 @@ public abstract class AnnotationUtils { /** * Get the name of the aliased attribute configured via * {@link AliasFor @AliasFor} on the supplied annotation {@code attribute}. - * * @param attribute the attribute to find an alias for * @param targetAnnotationType the type of annotation in which the * aliased attribute is allowed to be declared; {@code null} implies @@ -1481,7 +1462,8 @@ public abstract class AnnotationUtils { Class aliasedAnnotationType = aliasFor.annotation(); boolean searchWithinSameAnnotation = (targetAnnotationType == null); - boolean sameTargetDeclared = (sourceAnnotationType.equals(aliasedAnnotationType) || Annotation.class.equals(aliasedAnnotationType)); + boolean sameTargetDeclared = + (sourceAnnotationType.equals(aliasedAnnotationType) || Annotation.class.equals(aliasedAnnotationType)); // Wrong search scope? if (searchWithinSameAnnotation && !sameTargetDeclared) { @@ -1502,30 +1484,30 @@ public abstract class AnnotationUtils { aliasedAnnotationType = sourceAnnotationType; } - Method aliasedAttribute = null; + Method aliasedAttribute; try { aliasedAttribute = aliasedAnnotationType.getDeclaredMethod(aliasedAttributeName); } - catch (NoSuchMethodException e) { + catch (NoSuchMethodException ex) { String msg = String.format( - "Attribute [%s] in annotation [%s] is declared as an @AliasFor nonexistent attribute [%s] in annotation [%s].", - attributeName, sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); - throw new AnnotationConfigurationException(msg, e); + "Attribute [%s] in annotation [%s] is declared as an @AliasFor nonexistent attribute [%s] in annotation [%s].", + attributeName, sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); + throw new AnnotationConfigurationException(msg, ex); } if (sameTargetDeclared) { AliasFor mirrorAliasFor = aliasedAttribute.getAnnotation(AliasFor.class); if (mirrorAliasFor == null) { String msg = String.format("Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s].", - aliasedAttributeName, sourceAnnotationType.getName(), attributeName); + aliasedAttributeName, sourceAnnotationType.getName(), attributeName); throw new AnnotationConfigurationException(msg); } String mirrorAliasedAttributeName = mirrorAliasFor.attribute(); if (!attributeName.equals(mirrorAliasedAttributeName)) { String msg = String.format( - "Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s], not [%s].", - aliasedAttributeName, sourceAnnotationType.getName(), attributeName, mirrorAliasedAttributeName); + "Attribute [%s] in annotation [%s] must be declared as an @AliasFor [%s], not [%s].", + aliasedAttributeName, sourceAnnotationType.getName(), attributeName, mirrorAliasedAttributeName); throw new AnnotationConfigurationException(msg); } } @@ -1533,9 +1515,9 @@ public abstract class AnnotationUtils { Class returnType = attribute.getReturnType(); Class aliasedReturnType = aliasedAttribute.getReturnType(); if (!returnType.equals(aliasedReturnType)) { - String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " - + "and attribute [%s] in annotation [%s] must declare the same return type.", attributeName, - sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); + String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " + + "and attribute [%s] in annotation [%s] must declare the same return type.", attributeName, + sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); throw new AnnotationConfigurationException(msg); } @@ -1544,16 +1526,16 @@ public abstract class AnnotationUtils { Object aliasedDefaultValue = aliasedAttribute.getDefaultValue(); if ((defaultValue == null) || (aliasedDefaultValue == null)) { - String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " - + "and attribute [%s] in annotation [%s] must declare default values.", attributeName, - sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); + String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " + + "and attribute [%s] in annotation [%s] must declare default values.", attributeName, + sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); throw new AnnotationConfigurationException(msg); } if (!ObjectUtils.nullSafeEquals(defaultValue, aliasedDefaultValue)) { - String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " - + "and attribute [%s] in annotation [%s] must declare the same default value.", attributeName, - sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); + String msg = String.format("Misconfigured aliases: attribute [%s] in annotation [%s] " + + "and attribute [%s] in annotation [%s] must declare the same default value.", attributeName, + sourceAnnotationType.getName(), aliasedAttributeName, aliasedAnnotationType.getName()); throw new AnnotationConfigurationException(msg); } } @@ -1564,10 +1546,8 @@ public abstract class AnnotationUtils { /** * Get all methods declared in the supplied {@code annotationType} that * match Java's requirements for annotation attributes. - * *

All methods in the returned list will be * {@linkplain ReflectionUtils#makeAccessible(Method) made accessible}. - * * @param annotationType the type in which to search for attribute methods; * never {@code null} * @return all annotation attribute methods in the specified annotation @@ -1575,7 +1555,6 @@ public abstract class AnnotationUtils { * @since 4.2 */ static List getAttributeMethods(Class annotationType) { - List methods = attributeMethodsCache.get(annotationType); if (methods != null) { return methods; @@ -1590,7 +1569,6 @@ public abstract class AnnotationUtils { } attributeMethodsCache.put(annotationType, methods); - return methods; } @@ -1618,7 +1596,7 @@ public abstract class AnnotationUtils { * @return {@code true} if the method is an attribute method */ static boolean isAttributeMethod(Method method) { - return ((method != null) && (method.getParameterTypes().length == 0) && (method.getReturnType() != void.class)); + return (method != null && method.getParameterTypes().length == 0 && method.getReturnType() != void.class); } /** @@ -1627,17 +1605,15 @@ public abstract class AnnotationUtils { * @see Annotation#annotationType() */ static boolean isAnnotationTypeMethod(Method method) { - return ((method != null) && method.getName().equals("annotationType") && (method.getParameterTypes().length == 0)); + return (method != null && method.getName().equals("annotationType") && method.getParameterTypes().length == 0); } /** * Post-process the supplied {@link AnnotationAttributes}. - * *

Specifically, this method enforces attribute alias semantics * for annotation attributes that are annotated with {@link AliasFor @AliasFor} * and replaces {@linkplain #DEFAULT_VALUE_PLACEHOLDER placeholders} with their * original default values. - * * @param element the element that is annotated with an annotation or * annotation hierarchy from which the supplied attributes were created; * may be {@code null} if unknown @@ -1715,9 +1691,9 @@ public abstract class AnnotationUtils { * @param t the throwable to inspect * @since 4.2 */ - static void rethrowAnnotationConfigurationException(Throwable t) { - if (t instanceof AnnotationConfigurationException) { - throw (AnnotationConfigurationException) t; + static void rethrowAnnotationConfigurationException(Throwable ex) { + if (ex instanceof AnnotationConfigurationException) { + throw (AnnotationConfigurationException) ex; } } @@ -1731,13 +1707,11 @@ public abstract class AnnotationUtils { * Class values were not resolvable within annotation attributes and * thereby effectively pretending there were no annotations on the specified * element. - * * @param element the element that we tried to introspect annotations on * @param ex the exception that we encountered * @see #rethrowAnnotationConfigurationException */ static void handleIntrospectionFailure(AnnotatedElement element, Exception ex) { - rethrowAnnotationConfigurationException(ex); Log loggerToUse = logger; @@ -1745,7 +1719,7 @@ public abstract class AnnotationUtils { loggerToUse = LogFactory.getLog(AnnotationUtils.class); logger = loggerToUse; } - if ((element instanceof Class) && Annotation.class.isAssignableFrom((Class) element)) { + if (element instanceof Class && Annotation.class.isAssignableFrom((Class) element)) { // Meta-annotation lookup on an annotation type if (loggerToUse.isDebugEnabled()) { loggerToUse.debug("Failed to introspect meta-annotations on [" + element + "]: " + ex); @@ -1798,7 +1772,6 @@ public abstract class AnnotationUtils { private static final String REPEATABLE_CLASS_NAME = "java.lang.annotation.Repeatable"; - private final Class annotationType; private final Class containerAnnotationType; @@ -1809,17 +1782,13 @@ public abstract class AnnotationUtils { private final Set result = new LinkedHashSet(); - AnnotationCollector(Class annotationType, Class containerAnnotationType, boolean declaredMode) { this.annotationType = annotationType; - this.containerAnnotationType = (containerAnnotationType != null ? containerAnnotationType - : resolveContainerAnnotationType(annotationType)); + this.containerAnnotationType = (containerAnnotationType != null ? containerAnnotationType : + resolveContainerAnnotationType(annotationType)); this.declaredMode = declaredMode; } - /** - * @since 4.2 - */ @SuppressWarnings("unchecked") static Class resolveContainerAnnotationType(Class annotationType) { try { @@ -1829,8 +1798,8 @@ public abstract class AnnotationUtils { return (Class) value; } } - catch (Exception e) { - handleIntrospectionFailure(annotationType, e); + catch (Exception ex) { + handleIntrospectionFailure(annotationType, ex); } return null; } diff --git a/spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java new file mode 100644 index 00000000000..af26f0a3455 --- /dev/null +++ b/spring-core/src/main/java/org/springframework/core/annotation/SynthesizingMethodParameter.java @@ -0,0 +1,59 @@ +/* + * Copyright 2002-2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.core.annotation; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import org.springframework.core.MethodParameter; + +/** + * A {@link MethodParameter} variant which synthesizes annotations + * based on overridden annotation attributes, e.g. as declared with + * {@link AliasFor @AliasFor}. + * + * @author Juergen Hoeller + * @author Sam Brannen + * @since 4.2 + * @see AnnotationUtils#synthesizeAnnotation + * @see AnnotationUtils#synthesizeAnnotationArray + */ +public class SynthesizingMethodParameter extends MethodParameter { + + /** + * Create a new {@code SynthesizingMethodParameter} for the given method. + * @param method the Method to specify a parameter for + * @param parameterIndex the index of the parameter: -1 for the method + * return type; 0 for the first method parameter; 1 for the second method + * parameter, etc. + */ + public SynthesizingMethodParameter(Method method, int parameterIndex) { + super(method, parameterIndex); + } + + + @Override + protected A adaptAnnotation(A annotation) { + return AnnotationUtils.synthesizeAnnotation(annotation, getAnnotatedElement()); + } + + @Override + protected Annotation[] adaptAnnotationArray(Annotation[] annotations) { + return AnnotationUtils.synthesizeAnnotationArray(annotations, getAnnotatedElement()); + } + +} diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java index 33538c2976a..b7898d3ef4a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/HandlerMethod.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.core.BridgeMethodResolver; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -258,7 +259,7 @@ public class HandlerMethod { /** * A MethodParameter with HandlerMethod-specific behavior. */ - protected class HandlerMethodParameter extends MethodParameter { + protected class HandlerMethodParameter extends SynthesizingMethodParameter { public HandlerMethodParameter(int index) { super(HandlerMethod.this.bridgedMethod, index); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java index 6985c9eb488..429b5ce8acc 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/HeaderMethodArgumentResolverTests.java @@ -27,6 +27,7 @@ import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.GenericTypeResolver; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandlingException; @@ -62,16 +63,17 @@ public class HeaderMethodArgumentResolverTests { Method method = getClass().getDeclaredMethod("handleMessage", String.class, String.class, String.class, String.class, String.class); - this.paramRequired = new MethodParameter(method, 0); - this.paramNamedDefaultValueStringHeader = new MethodParameter(method, 1); - this.paramSystemProperty = new MethodParameter(method, 2); - this.paramNotAnnotated = new MethodParameter(method, 3); - this.paramNativeHeader = new MethodParameter(method, 4); + this.paramRequired = new SynthesizingMethodParameter(method, 0); + this.paramNamedDefaultValueStringHeader = new SynthesizingMethodParameter(method, 1); + this.paramSystemProperty = new SynthesizingMethodParameter(method, 2); + this.paramNotAnnotated = new SynthesizingMethodParameter(method, 3); + this.paramNativeHeader = new SynthesizingMethodParameter(method, 4); this.paramRequired.initParameterNameDiscovery(new DefaultParameterNameDiscoverer()); GenericTypeResolver.resolveParameterType(this.paramRequired, HeaderMethodArgumentResolver.class); } + @Test public void supportsParameter() { assertTrue(resolver.supportsParameter(paramNamedDefaultValueStringHeader)); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java index 2c40b6b465e..ffc09541095 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -30,12 +30,12 @@ import org.junit.rules.ExpectedException; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.messaging.Message; import org.springframework.messaging.converter.MessageConversionException; import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.messaging.support.MessageBuilder; -import org.springframework.util.Assert; import org.springframework.validation.Errors; import org.springframework.validation.Validator; import org.springframework.validation.annotation.Validated; @@ -80,14 +80,14 @@ public class PayloadArgumentResolverTests { this.payloadMethod = PayloadArgumentResolverTests.class.getDeclaredMethod("handleMessage", String.class, String.class, Locale.class, String.class, String.class, String.class, String.class); - this.paramAnnotated = getMethodParameter(this.payloadMethod, 0); - this.paramAnnotatedNotRequired = getMethodParameter(this.payloadMethod, 1); - this.paramAnnotatedRequired = getMethodParameter(payloadMethod, 2); - this.paramWithSpelExpression = getMethodParameter(payloadMethod, 3); - this.paramValidated = getMethodParameter(this.payloadMethod, 4); + this.paramAnnotated = new SynthesizingMethodParameter(this.payloadMethod, 0); + this.paramAnnotatedNotRequired = new SynthesizingMethodParameter(this.payloadMethod, 1); + this.paramAnnotatedRequired = new SynthesizingMethodParameter(payloadMethod, 2); + this.paramWithSpelExpression = new SynthesizingMethodParameter(payloadMethod, 3); + this.paramValidated = new SynthesizingMethodParameter(this.payloadMethod, 4); this.paramValidated.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); - this.paramValidatedNotAnnotated = getMethodParameter(this.payloadMethod, 5); - this.paramNotAnnotated = getMethodParameter(this.payloadMethod, 6); + this.paramValidatedNotAnnotated = new SynthesizingMethodParameter(this.payloadMethod, 5); + this.paramNotAnnotated = new SynthesizingMethodParameter(this.payloadMethod, 6); } @@ -204,10 +204,6 @@ public class PayloadArgumentResolverTests { }; } - private MethodParameter getMethodParameter(Method method, int index) { - Assert.notNull(method, "Method must be set"); - return new MethodParameter(method, index); - } @SuppressWarnings("unused") private void handleMessage( diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java index eec22554053..78a2bb02be7 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/annotation/support/SendToMethodReturnValueHandlerTests.java @@ -16,20 +16,17 @@ package org.springframework.messaging.simp.annotation.support; -import com.fasterxml.jackson.annotation.JsonView; - import java.lang.reflect.Method; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.util.LinkedHashMap; import java.util.Map; - import javax.security.auth.Subject; +import com.fasterxml.jackson.annotation.JsonView; import org.junit.Before; import org.junit.Test; - import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; @@ -37,6 +34,7 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHeaders; @@ -56,7 +54,7 @@ import org.springframework.util.MimeType; import static org.junit.Assert.*; import static org.mockito.BDDMockito.*; -import static org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver.DESTINATION_TEMPLATE_VARIABLES_HEADER; +import static org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver.*; import static org.springframework.messaging.support.MessageHeaderAccessor.*; /** @@ -95,7 +93,6 @@ public class SendToMethodReturnValueHandlerTests { @Before public void setup() throws Exception { - MockitoAnnotations.initMocks(this); SimpMessagingTemplate messagingTemplate = new SimpMessagingTemplate(this.messageChannel); @@ -108,31 +105,31 @@ public class SendToMethodReturnValueHandlerTests { this.jsonHandler = new SendToMethodReturnValueHandler(jsonMessagingTemplate, true); Method method = this.getClass().getDeclaredMethod("handleNoAnnotations"); - this.noAnnotationsReturnType = new MethodParameter(method, -1); + this.noAnnotationsReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToDefaultDestination"); - this.sendToDefaultDestReturnType = new MethodParameter(method, -1); + this.sendToDefaultDestReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendTo"); - this.sendToReturnType = new MethodParameter(method, -1); + this.sendToReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToWithPlaceholders"); - this.sendToWithPlaceholdersReturnType = new MethodParameter(method, -1); + this.sendToWithPlaceholdersReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToUser"); - this.sendToUserReturnType = new MethodParameter(method, -1); + this.sendToUserReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToUserSingleSession"); - this.sendToUserSingleSessionReturnType = new MethodParameter(method, -1); + this.sendToUserSingleSessionReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToUserDefaultDestination"); - this.sendToUserDefaultDestReturnType = new MethodParameter(method, -1); + this.sendToUserDefaultDestReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToUserDefaultDestinationSingleSession"); - this.sendToUserSingleSessionDefaultDestReturnType = new MethodParameter(method, -1); + this.sendToUserSingleSessionDefaultDestReturnType = new SynthesizingMethodParameter(method, -1); method = this.getClass().getDeclaredMethod("handleAndSendToJsonView"); - this.jsonViewReturnType = new MethodParameter(method, -1); + this.jsonViewReturnType = new SynthesizingMethodParameter(method, -1); } diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java index ff66d18c9ba..eb8693338ca 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/support/HandlerMethodInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -43,6 +43,7 @@ import org.springframework.core.GenericTypeResolver; import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; @@ -241,7 +242,7 @@ public class HandlerMethodInvoker { Object[] args = new Object[paramTypes.length]; for (int i = 0; i < args.length; i++) { - MethodParameter methodParam = new MethodParameter(handlerMethod, i); + MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i); methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer); GenericTypeResolver.resolveParameterType(methodParam, handler.getClass()); String paramName = null; @@ -420,7 +421,7 @@ public class HandlerMethodInvoker { Object[] initBinderArgs = new Object[initBinderParams.length]; for (int i = 0; i < initBinderArgs.length; i++) { - MethodParameter methodParam = new MethodParameter(initBinderMethod, i); + MethodParameter methodParam = new SynthesizingMethodParameter(initBinderMethod, i); methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer); GenericTypeResolver.resolveParameterType(methodParam, handler.getClass()); String paramName = null; diff --git a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java index 6905dce9591..5be84c00774 100644 --- a/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java +++ b/spring-web/src/main/java/org/springframework/web/method/HandlerMethod.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.core.BridgeMethodResolver; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -268,7 +269,7 @@ public class HandlerMethod { /** * A MethodParameter with HandlerMethod-specific behavior. */ - protected class HandlerMethodParameter extends MethodParameter { + protected class HandlerMethodParameter extends SynthesizingMethodParameter { public HandlerMethodParameter(int index) { super(HandlerMethod.this.bridgedMethod, index); diff --git a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java index c209c52c062..3ef1b4fea83 100644 --- a/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java +++ b/spring-web/src/main/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolver.java @@ -55,8 +55,8 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho @Override public boolean supportsParameter(MethodParameter parameter) { - return parameter.hasParameterAnnotation(RequestHeader.class) && - !Map.class.isAssignableFrom(parameter.getParameterType()); + return (parameter.hasParameterAnnotation(RequestHeader.class) && + !Map.class.isAssignableFrom(parameter.getParameterType())); } @Override 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 f061d86ed22..1df794a7c51 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -117,16 +117,16 @@ public class CompositeUriComponentsContributor implements UriComponentsContribut public void contributeMethodArgument(MethodParameter parameter, Object value, UriComponentsBuilder builder, Map uriVariables, ConversionService conversionService) { - for (Object c : this.contributors) { - if (c instanceof UriComponentsContributor) { - UriComponentsContributor contributor = (UriComponentsContributor) c; - if (contributor.supportsParameter(parameter)) { - contributor.contributeMethodArgument(parameter, value, builder, uriVariables, conversionService); + for (Object contributor : this.contributors) { + if (contributor instanceof UriComponentsContributor) { + UriComponentsContributor ucc = (UriComponentsContributor) contributor; + if (ucc.supportsParameter(parameter)) { + ucc.contributeMethodArgument(parameter, value, builder, uriVariables, conversionService); break; } } - else if (c instanceof HandlerMethodArgumentResolver) { - if (((HandlerMethodArgumentResolver) c).supportsParameter(parameter)) { + else if (contributor instanceof HandlerMethodArgumentResolver) { + if (((HandlerMethodArgumentResolver) contributor).supportsParameter(parameter)) { break; } } diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/CookieValueMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/CookieValueMethodArgumentResolverTests.java index 0181b63a5da..e1f9929a737 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/CookieValueMethodArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/CookieValueMethodArgumentResolverTests.java @@ -23,6 +23,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.web.bind.ServletRequestBindingException; @@ -52,19 +53,21 @@ public class CookieValueMethodArgumentResolverTests { private MockHttpServletRequest request; + @Before public void setUp() throws Exception { resolver = new TestCookieValueMethodArgumentResolver(); Method method = getClass().getMethod("params", Cookie.class, String.class, String.class); - paramNamedCookie = new MethodParameter(method, 0); - paramNamedDefaultValueString = new MethodParameter(method, 1); - paramString = new MethodParameter(method, 2); + paramNamedCookie = new SynthesizingMethodParameter(method, 0); + paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 1); + paramString = new SynthesizingMethodParameter(method, 2); request = new MockHttpServletRequest(); webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); } + @Test public void supportsParameter() { assertTrue("Cookie parameter not supported", resolver.supportsParameter(paramNamedCookie)); @@ -98,9 +101,10 @@ public class CookieValueMethodArgumentResolverTests { } } + public void params(@CookieValue("name") Cookie param1, @CookieValue(name = "name", defaultValue = "bar") String param2, String param3) { } -} \ No newline at end of file +} diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMapMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMapMethodArgumentResolverTests.java index e86446ddeef..ef2a3f01831 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMapMethodArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMapMethodArgumentResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; @@ -57,20 +58,22 @@ public class RequestHeaderMapMethodArgumentResolverTests { private MockHttpServletRequest request; + @Before public void setUp() throws Exception { resolver = new RequestHeaderMapMethodArgumentResolver(); Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, HttpHeaders.class, Map.class); - paramMap = new MethodParameter(method, 0); - paramMultiValueMap = new MethodParameter(method, 1); - paramHttpHeaders = new MethodParameter(method, 2); - paramUnsupported = new MethodParameter(method, 3); + paramMap = new SynthesizingMethodParameter(method, 0); + paramMultiValueMap = new SynthesizingMethodParameter(method, 1); + paramHttpHeaders = new SynthesizingMethodParameter(method, 2); + paramUnsupported = new SynthesizingMethodParameter(method, 3); request = new MockHttpServletRequest(); webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); } + @Test public void supportsParameter() { assertTrue("Map parameter not supported", resolver.supportsParameter(paramMap)); @@ -130,10 +133,11 @@ public class RequestHeaderMapMethodArgumentResolverTests { assertEquals("Invalid result", expected, result); } + public void params(@RequestHeader Map param1, @RequestHeader MultiValueMap param2, @RequestHeader HttpHeaders param3, Map unsupported) { } -} \ No newline at end of file +} diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java index 0895749867a..ecf30430ee5 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestHeaderMethodArgumentResolverTests.java @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.web.bind.ServletRequestBindingException; @@ -55,6 +56,7 @@ public class RequestHeaderMethodArgumentResolverTests { private NativeWebRequest webRequest; + @Before public void setUp() throws Exception { GenericWebApplicationContext context = new GenericWebApplicationContext(); @@ -62,11 +64,11 @@ public class RequestHeaderMethodArgumentResolverTests { resolver = new RequestHeaderMethodArgumentResolver(context.getBeanFactory()); Method method = getClass().getMethod("params", String.class, String[].class, String.class, String.class, Map.class); - paramNamedDefaultValueStringHeader = new MethodParameter(method, 0); - paramNamedValueStringArray = new MethodParameter(method, 1); - paramSystemProperty = new MethodParameter(method, 2); - paramContextPath = new MethodParameter(method, 3); - paramNamedValueMap = new MethodParameter(method, 4); + paramNamedDefaultValueStringHeader = new SynthesizingMethodParameter(method, 0); + paramNamedValueStringArray = new SynthesizingMethodParameter(method, 1); + paramSystemProperty = new SynthesizingMethodParameter(method, 2); + paramContextPath = new SynthesizingMethodParameter(method, 3); + paramNamedValueMap = new SynthesizingMethodParameter(method, 4); servletRequest = new MockHttpServletRequest(); webRequest = new ServletWebRequest(servletRequest, new MockHttpServletResponse()); @@ -80,6 +82,7 @@ public class RequestHeaderMethodArgumentResolverTests { RequestContextHolder.resetRequestAttributes(); } + @Test public void supportsParameter() { assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueStringHeader)); @@ -141,6 +144,7 @@ public class RequestHeaderMethodArgumentResolverTests { resolver.resolveArgument(paramNamedValueStringArray, null, webRequest, null); } + public void params(@RequestHeader(name = "name", defaultValue = "bar") String param1, @RequestHeader("name") String[] param2, @RequestHeader(name = "name", defaultValue="#{systemProperties.systemProperty}") String param3, @@ -148,4 +152,4 @@ public class RequestHeaderMethodArgumentResolverTests { @RequestHeader("name") Map unsupported) { } -} \ No newline at end of file +} diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMapMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMapMethodArgumentResolverTests.java index 1aa9d371f84..cae73f460d7 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMapMethodArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMapMethodArgumentResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.util.LinkedMultiValueMap; @@ -56,20 +57,22 @@ public class RequestParamMapMethodArgumentResolverTests { private MockHttpServletRequest request; + @Before public void setUp() throws Exception { resolver = new RequestParamMapMethodArgumentResolver(); Method method = getClass().getMethod("params", Map.class, MultiValueMap.class, Map.class, Map.class); - paramMap = new MethodParameter(method, 0); - paramMultiValueMap = new MethodParameter(method, 1); - paramNamedMap = new MethodParameter(method, 2); - paramMapWithoutAnnot = new MethodParameter(method, 3); + paramMap = new SynthesizingMethodParameter(method, 0); + paramMultiValueMap = new SynthesizingMethodParameter(method, 1); + paramNamedMap = new SynthesizingMethodParameter(method, 2); + paramMapWithoutAnnot = new SynthesizingMethodParameter(method, 3); request = new MockHttpServletRequest(); webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); } + @Test public void supportsParameter() { assertTrue("Map parameter not supported", resolver.supportsParameter(paramMap)); @@ -108,10 +111,11 @@ public class RequestParamMapMethodArgumentResolverTests { assertEquals("Invalid result", expected, result); } + public void params(@RequestParam Map param1, @RequestParam MultiValueMap param2, @RequestParam("name") Map param3, Map param4) { } -} \ No newline at end of file +} diff --git a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java index 926ede0ebb2..4617715a8ca 100644 --- a/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java +++ b/spring-web/src/test/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolverTests.java @@ -21,7 +21,6 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; - import javax.servlet.http.Part; import org.junit.Before; @@ -31,6 +30,7 @@ import org.springframework.beans.propertyeditors.StringTrimmerEditor; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; @@ -99,28 +99,28 @@ public class RequestParamMethodArgumentResolverTests { String.class, MultipartFile.class, List.class, Part.class, MultipartFile.class, String.class, String.class, Optional.class); - paramNamedDefaultValueString = new MethodParameter(method, 0); - paramNamedStringArray = new MethodParameter(method, 1); - paramNamedMap = new MethodParameter(method, 2); - paramMultipartFile = new MethodParameter(method, 3); - paramMultipartFileList = new MethodParameter(method, 4); - paramMultipartFileArray = new MethodParameter(method, 5); - paramPart = new MethodParameter(method, 6); - paramPartList = new MethodParameter(method, 7); - paramPartArray = new MethodParameter(method, 8); - paramMap = new MethodParameter(method, 9); - paramStringNotAnnot = new MethodParameter(method, 10); + paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0); + paramNamedStringArray = new SynthesizingMethodParameter(method, 1); + paramNamedMap = new SynthesizingMethodParameter(method, 2); + paramMultipartFile = new SynthesizingMethodParameter(method, 3); + paramMultipartFileList = new SynthesizingMethodParameter(method, 4); + paramMultipartFileArray = new SynthesizingMethodParameter(method, 5); + paramPart = new SynthesizingMethodParameter(method, 6); + paramPartList = new SynthesizingMethodParameter(method, 7); + paramPartArray = new SynthesizingMethodParameter(method, 8); + paramMap = new SynthesizingMethodParameter(method, 9); + paramStringNotAnnot = new SynthesizingMethodParameter(method, 10); paramStringNotAnnot.initParameterNameDiscovery(paramNameDiscoverer); - paramMultipartFileNotAnnot = new MethodParameter(method, 11); + paramMultipartFileNotAnnot = new SynthesizingMethodParameter(method, 11); paramMultipartFileNotAnnot.initParameterNameDiscovery(paramNameDiscoverer); - paramMultipartFileListNotAnnot = new MethodParameter(method, 12); + paramMultipartFileListNotAnnot = new SynthesizingMethodParameter(method, 12); paramMultipartFileListNotAnnot.initParameterNameDiscovery(paramNameDiscoverer); - paramPartNotAnnot = new MethodParameter(method, 13); + paramPartNotAnnot = new SynthesizingMethodParameter(method, 13); paramPartNotAnnot.initParameterNameDiscovery(paramNameDiscoverer); - paramRequestPartAnnot = new MethodParameter(method, 14); - paramRequired = new MethodParameter(method, 15); - paramNotRequired = new MethodParameter(method, 16); - paramOptional = new MethodParameter(method, 17); + paramRequestPartAnnot = new SynthesizingMethodParameter(method, 14); + paramRequired = new SynthesizingMethodParameter(method, 15); + paramNotRequired = new SynthesizingMethodParameter(method, 16); + paramOptional = new SynthesizingMethodParameter(method, 17); request = new MockHttpServletRequest(); webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); diff --git a/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java b/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java index 0764dd0d442..31e1b86db57 100644 --- a/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java +++ b/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -49,6 +49,7 @@ import org.springframework.core.ExceptionDepthComparator; import org.springframework.core.GenericTypeResolver; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.ui.Model; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; @@ -233,7 +234,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc Object[] args = new Object[paramTypes.length]; Class handlerType = handler.getClass(); for (int i = 0; i < args.length; i++) { - MethodParameter methodParam = new MethodParameter(handlerMethod, i); + MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i); GenericTypeResolver.resolveParameterType(methodParam, handlerType); Class paramType = methodParam.getParameterType(); Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException); diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java index 8c823892466..ab26750443b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -44,6 +44,7 @@ import org.springframework.core.ExceptionDepthComparator; import org.springframework.core.GenericTypeResolver; import org.springframework.core.MethodParameter; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.HttpStatus; @@ -258,7 +259,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc Object[] args = new Object[paramTypes.length]; Class handlerType = handler.getClass(); for (int i = 0; i < args.length; i++) { - MethodParameter methodParam = new MethodParameter(handlerMethod, i); + MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i); GenericTypeResolver.resolveParameterType(methodParam, handlerType); Class paramType = methodParam.getParameterType(); Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException); 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 3c5dd8a5d82..85b4bc35492 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 @@ -41,6 +41,7 @@ import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.objenesis.ObjenesisException; import org.springframework.objenesis.SpringObjenesis; import org.springframework.util.AntPathMatcher; @@ -486,7 +487,7 @@ public class MvcUriComponentsBuilder { final Map uriVars = new HashMap(); for (int i = 0; i < paramCount; i++) { - MethodParameter param = new MethodParameter(method, i); + MethodParameter param = new SynthesizingMethodParameter(method, i); param.initParameterNameDiscovery(parameterNameDiscoverer); contributor.contributeMethodArgument(param, args[i], builder, uriVars); } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java index 09068e9d2b7..59d59d8f998 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolver.java @@ -75,7 +75,6 @@ import org.springframework.web.util.WebUtils; */ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterMethodArgumentResolver { - /** * Basic constructor with converters only. */ diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java index 6dabf427163..f4fe3ac3647 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -26,6 +26,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.util.LinkedMultiValueMap; @@ -66,11 +67,11 @@ public class MatrixVariablesMapMethodArgumentResolverTests { Method method = getClass().getMethod("handle", String.class, Map.class, MultiValueMap.class, MultiValueMap.class, Map.class); - this.paramString = new MethodParameter(method, 0); - this.paramMap = new MethodParameter(method, 1); - this.paramMultivalueMap = new MethodParameter(method, 2); - this.paramMapForPathVar = new MethodParameter(method, 3); - this.paramMapWithName = new MethodParameter(method, 4); + this.paramString = new SynthesizingMethodParameter(method, 0); + this.paramMap = new SynthesizingMethodParameter(method, 1); + this.paramMultivalueMap = new SynthesizingMethodParameter(method, 2); + this.paramMapForPathVar = new SynthesizingMethodParameter(method, 3); + this.paramMapWithName = new SynthesizingMethodParameter(method, 4); this.mavContainer = new ModelAndViewContainer(); this.request = new MockHttpServletRequest(); @@ -91,7 +92,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests { @Test public void resolveArgument() throws Exception { - MultiValueMap params = getMatrixVariables("cars"); params.add("colors", "red"); params.add("colors", "green"); @@ -113,7 +113,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests { @Test public void resolveArgumentPathVariable() throws Exception { - MultiValueMap params1 = getMatrixVariables("cars"); params1.add("colors", "red"); params1.add("colors", "purple"); @@ -137,7 +136,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests { @Test public void resolveArgumentNoParams() throws Exception { - @SuppressWarnings("unchecked") Map map = (Map) this.resolver.resolveArgument( this.paramMap, this.mavContainer, this.webRequest, null); @@ -147,7 +145,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests { @Test public void resolveArgumentNoMatch() throws Exception { - MultiValueMap params2 = getMatrixVariables("planes"); params2.add("colors", "yellow"); params2.add("colors", "orange"); @@ -162,7 +159,6 @@ public class MatrixVariablesMapMethodArgumentResolverTests { @SuppressWarnings("unchecked") private MultiValueMap getMatrixVariables(String pathVarName) { - Map> matrixVariables = (Map>) this.request.getAttribute( HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE); @@ -182,4 +178,4 @@ public class MatrixVariablesMapMethodArgumentResolverTests { @MatrixVariable("name") Map mapWithName) { } -} \ No newline at end of file +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java index d3a04537dd8..5b443ff7fdb 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartMethodArgumentResolverTests.java @@ -16,16 +16,12 @@ package org.springframework.web.servlet.mvc.method.annotation; -import static org.junit.Assert.*; -import static org.mockito.BDDMockito.*; - import java.lang.reflect.Method; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; - import javax.servlet.http.Part; import javax.validation.Valid; import javax.validation.constraints.NotNull; @@ -36,6 +32,7 @@ import org.junit.Test; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.http.HttpInputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; @@ -58,6 +55,9 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.support.MissingServletRequestPartException; import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest; +import static org.junit.Assert.*; +import static org.mockito.BDDMockito.*; + /** * Test fixture with {@link RequestPartMethodArgumentResolver} and mock {@link HttpMessageConverter}. * @@ -102,26 +102,26 @@ public class RequestPartMethodArgumentResolverTests { Integer.TYPE, MultipartFile.class, Part.class, List.class, Part[].class, MultipartFile.class, Optional.class, Optional.class, Optional.class); - paramRequestPart = new MethodParameter(method, 0); + paramRequestPart = new SynthesizingMethodParameter(method, 0); paramRequestPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); - paramNamedRequestPart = new MethodParameter(method, 1); - paramValidRequestPart = new MethodParameter(method, 2); - paramMultipartFile = new MethodParameter(method, 3); - paramMultipartFileList = new MethodParameter(method, 4); - paramMultipartFileArray = new MethodParameter(method, 5); - paramInt = new MethodParameter(method, 6); - paramMultipartFileNotAnnot = new MethodParameter(method, 7); + paramNamedRequestPart = new SynthesizingMethodParameter(method, 1); + paramValidRequestPart = new SynthesizingMethodParameter(method, 2); + paramMultipartFile = new SynthesizingMethodParameter(method, 3); + paramMultipartFileList = new SynthesizingMethodParameter(method, 4); + paramMultipartFileArray = new SynthesizingMethodParameter(method, 5); + paramInt = new SynthesizingMethodParameter(method, 6); + paramMultipartFileNotAnnot = new SynthesizingMethodParameter(method, 7); paramMultipartFileNotAnnot.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); - paramPart = new MethodParameter(method, 8); + paramPart = new SynthesizingMethodParameter(method, 8); paramPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); - paramPartList = new MethodParameter(method, 9); - paramPartArray = new MethodParameter(method, 10); - paramRequestParamAnnot = new MethodParameter(method, 11); - optionalMultipartFile = new MethodParameter(method, 12); + paramPartList = new SynthesizingMethodParameter(method, 9); + paramPartArray = new SynthesizingMethodParameter(method, 10); + paramRequestParamAnnot = new SynthesizingMethodParameter(method, 11); + optionalMultipartFile = new SynthesizingMethodParameter(method, 12); optionalMultipartFile.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); - optionalPart = new MethodParameter(method, 13); + optionalPart = new SynthesizingMethodParameter(method, 13); optionalPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer()); - optionalRequestPart = new MethodParameter(method, 14); + optionalRequestPart = new SynthesizingMethodParameter(method, 14); messageConverter = mock(HttpMessageConverter.class); given(messageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolverTests.java index cd18d1e959e..5796f1248f3 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletCookieValueMethodArgumentResolverTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 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. @@ -23,6 +23,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.web.bind.annotation.CookieValue; @@ -48,18 +49,20 @@ public class ServletCookieValueMethodArgumentResolverTests { private MockHttpServletRequest request; + @Before public void setUp() throws Exception { resolver = new ServletCookieValueMethodArgumentResolver(null); Method method = getClass().getMethod("params", Cookie.class, String.class); - cookieParameter = new MethodParameter(method, 0); - cookieStringParameter = new MethodParameter(method, 1); + cookieParameter = new SynthesizingMethodParameter(method, 0); + cookieStringParameter = new SynthesizingMethodParameter(method, 1); request = new MockHttpServletRequest(); webRequest = new ServletWebRequest(request, new MockHttpServletResponse()); } + @Test public void resolveCookieArgument() throws Exception { Cookie expected = new Cookie("name", "foo"); @@ -78,8 +81,9 @@ public class ServletCookieValueMethodArgumentResolverTests { assertEquals("Invalid result", cookie.getValue(), result); } + public void params(@CookieValue("name") Cookie cookie, @CookieValue(name = "name", defaultValue = "bar") String cookieString) { } -} \ No newline at end of file +}