diff --git a/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolverSupport.java b/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolverSupport.java index 614af60ea1..7978d689a9 100644 --- a/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolverSupport.java +++ b/src/main/java/org/springframework/data/web/SortHandlerMethodArgumentResolverSupport.java @@ -22,14 +22,15 @@ import java.util.Optional; import java.util.function.Consumer; -import javax.annotation.Nullable; - import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.MergedAnnotation; +import org.springframework.core.annotation.MergedAnnotations; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; import org.springframework.data.web.SortDefault.SortDefaults; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -41,6 +42,7 @@ * @see SortHandlerMethodArgumentResolver * @see ReactiveSortHandlerMethodArgumentResolver * @author Mark Paluch + * @author Vedran Pavic */ public abstract class SortHandlerMethodArgumentResolverSupport { @@ -184,10 +186,10 @@ protected String getSortParameter(@Nullable MethodParameter parameter) { StringBuilder builder = new StringBuilder(); - Qualifier qualifier = parameter != null ? parameter.getParameterAnnotation(Qualifier.class) : null; + String value = getQualifier(parameter); - if (qualifier != null && StringUtils.hasLength(qualifier.value())) { - builder.append(qualifier.value()); + if (StringUtils.hasLength(value)) { + builder.append(value); builder.append(qualifierDelimiter); } @@ -293,6 +295,19 @@ static boolean notOnlyDots(String source) { return StringUtils.hasText(source.replace(".", "")); } + @Nullable + private static String getQualifier(@Nullable MethodParameter parameter) { + + if (parameter == null) { + return null; + } + + MergedAnnotations annotations = MergedAnnotations.from(parameter.getParameter()); + MergedAnnotation qualifier = annotations.get(Qualifier.class); + + return qualifier.isPresent() ? qualifier.getString("value") : null; + } + /** * Helper to easily build request parameter expressions for {@link Sort} instances. * diff --git a/src/test/java/org/springframework/data/web/PageableHandlerMethodArgumentResolverUnitTests.java b/src/test/java/org/springframework/data/web/PageableHandlerMethodArgumentResolverUnitTests.java index 295f63b5e6..c0f35327c4 100755 --- a/src/test/java/org/springframework/data/web/PageableHandlerMethodArgumentResolverUnitTests.java +++ b/src/test/java/org/springframework/data/web/PageableHandlerMethodArgumentResolverUnitTests.java @@ -257,6 +257,18 @@ void emptyQualifierIsUsedInParameterLookup() throws Exception { assertSupportedAndResult(parameter, PageRequest.of(2, 10), request); } + @Test // DATACMNS-1827 + void mergedQualifierIsUsedInParameterLookup() throws Exception { + + MethodParameter parameter = new MethodParameter(Sample.class.getMethod("mergedQualifier", Pageable.class), 0); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addParameter("merged_page", "2"); + request.addParameter("merged_size", "10"); + + assertSupportedAndResult(parameter, PageRequest.of(2, 10), request); + } + @Override protected PageableHandlerMethodArgumentResolver getResolver() { PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver(); @@ -298,5 +310,7 @@ void simpleDefaultWithContaineredExternalSort(@PageableDefault(size = PAGE_SIZE, void noQualifiers(Pageable first, Pageable second); void emptyQualifier(@Qualifier Pageable pageable); + + void mergedQualifier(@TestQualifier Pageable pageable); } } diff --git a/src/test/java/org/springframework/data/web/SortHandlerMethodArgumentResolverUnitTests.java b/src/test/java/org/springframework/data/web/SortHandlerMethodArgumentResolverUnitTests.java index e89a8361b6..eb65e4ece4 100755 --- a/src/test/java/org/springframework/data/web/SortHandlerMethodArgumentResolverUnitTests.java +++ b/src/test/java/org/springframework/data/web/SortHandlerMethodArgumentResolverUnitTests.java @@ -251,6 +251,15 @@ void emptyQualifierIsUsedInParameterLookup() { assertSupportedAndResolvedTo(getRequestWithSort(reference, ""), parameter, reference); } + @Test // DATACMNS-1827 + void mergedQualifierIsUsedInParameterLookup() { + + MethodParameter parameter = getParameterOfMethod("mergedQualifier"); + Sort reference = Sort.by("bar", "foo"); + + assertSupportedAndResolvedTo(getRequestWithSort(reference, "merged"), parameter, reference); + } + private static Sort resolveSort(HttpServletRequest request, MethodParameter parameter) throws Exception { SortHandlerMethodArgumentResolver resolver = new SortHandlerMethodArgumentResolver(); @@ -318,5 +327,7 @@ void simpleDefaultWithDirectionCaseInsensitive( void invalid(@SortDefaults(@SortDefault({ "foo", "bar" })) @SortDefault({ "bar", "foo" }) Sort sort); void emptyQualifier(@Qualifier Sort sort); + + void mergedQualifier(@TestQualifier Sort sort); } } diff --git a/src/test/java/org/springframework/data/web/TestQualifier.java b/src/test/java/org/springframework/data/web/TestQualifier.java new file mode 100644 index 0000000000..9c3f1d86a2 --- /dev/null +++ b/src/test/java/org/springframework/data/web/TestQualifier.java @@ -0,0 +1,37 @@ +/* + * Copyright 2020 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 + * + * https://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.data.web; + +import org.springframework.beans.factory.annotation.Qualifier; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author Vedran Pavic + * @see PageableHandlerMethodArgumentResolverUnitTests + * @see SortHandlerMethodArgumentResolverUnitTests + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@Qualifier("merged") +@interface TestQualifier { + +}