DATACMNS-236, DATACMNS-117 - Added (Pageable|Sort)HanderMethodArgumentResolvers.
Added HandlerMethodArgumentResolver implementations for Pageable and Sort exposing a new default set of properties (page, size, sort) to resolve pagination and sorting information from the request. To mimic the legacy behavior we expose a (deprecated) LEGACY constant in PageableHandlerMethodArgumentResolver. Clients should move to the new properties structure ASAP. Added unit tests to verify old and new defaulting behavior. Introduced new annotations @SortDefault (with @SortDefaults wrapper annotation) and @PageableDefault (superseding the legacy @PageableDefaults). The new annotations have more speaking attribute names and the HMAR implementations transparently alias the generic value attribute into a more semantic one (size). The HMAR implementations implement Spring HATEOAS' UriComponentsContributor to be able to turn Pageable / Sort instances back into URIs created through the MethodLinkBuilderFactory API in Spring HATEOAS. Extracted common API between legacy PageableArgumentResolver and PageableHandlerMethodArgumentResolver into common helper class. Upgraded to Spring Hateoas 0.5.0.BUILD-SNAPSHOT.
This commit is contained in:
@@ -17,6 +17,7 @@ package org.springframework.data.web;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.web.PageableHandlerMethodArgumentResolver.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -27,19 +28,22 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.web.SortDefault.SortDefaults;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PageableHandlerArgumentResolver}.
|
||||
* Unit tests for {@link PageableHandlerMethodArgumentResolver} in it's legacy mode. Essentially a copy of
|
||||
* {@link PageableArgumentResolverUnitTests} but but executed against {@link PageableHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class PageableHandlerArgumentResolverUnitTests {
|
||||
@SuppressWarnings("deprecation")
|
||||
public class LegacyPageableHandlerArgumentResolverUnitTests extends PageableDefaultUnitTest {
|
||||
|
||||
Method correctMethod, failedMethod, invalidQualifiers, defaultsMethod, defaultsMethodWithSort,
|
||||
Method correctMethod, noQualifiers, invalidQualifiers, defaultsMethod, defaultsMethodWithSort,
|
||||
defaultsMethodWithSortAndDirection, otherMethod;
|
||||
|
||||
MockHttpServletRequest request;
|
||||
@@ -48,13 +52,13 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
correctMethod = SampleController.class.getMethod("correctMethod", Pageable.class, Pageable.class);
|
||||
failedMethod = SampleController.class.getMethod("failedMethod", Pageable.class, Pageable.class);
|
||||
noQualifiers = SampleController.class.getMethod("noQualifiers", Pageable.class, Pageable.class);
|
||||
invalidQualifiers = SampleController.class.getMethod("invalidQualifiers", Pageable.class, Pageable.class);
|
||||
otherMethod = SampleController.class.getMethod("otherMethod", String.class);
|
||||
otherMethod = SampleController.class.getMethod("unsupportedMethod", String.class);
|
||||
|
||||
defaultsMethod = SampleController.class.getMethod("defaultsMethod", Pageable.class);
|
||||
defaultsMethodWithSort = SampleController.class.getMethod("defaultsMethodWithSort", Pageable.class);
|
||||
defaultsMethodWithSortAndDirection = SampleController.class.getMethod("defaultsMethodWithSortAndDirection",
|
||||
defaultsMethod = SampleController.class.getMethod("simpleDefault", Pageable.class);
|
||||
defaultsMethodWithSort = SampleController.class.getMethod("simpleDefaultWithSort", Pageable.class);
|
||||
defaultsMethodWithSortAndDirection = SampleController.class.getMethod("simpleDefaultWithSortAndDirection",
|
||||
Pageable.class);
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
@@ -71,14 +75,14 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
@Test
|
||||
public void supportsPageableParameter() {
|
||||
|
||||
PageableHandlerArgumentResolver resolver = new PageableHandlerArgumentResolver();
|
||||
PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
|
||||
resolver.supportsParameter(new MethodParameter(correctMethod, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotSupportNonPageableParameter() {
|
||||
|
||||
PageableHandlerArgumentResolver resolver = new PageableHandlerArgumentResolver();
|
||||
PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
|
||||
resolver.supportsParameter(new MethodParameter(otherMethod, 0));
|
||||
}
|
||||
|
||||
@@ -92,10 +96,10 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void rejectsInvalidlyMappedPageables() throws Exception {
|
||||
|
||||
MethodParameter parameter = new MethodParameter(failedMethod, 0);
|
||||
MethodParameter parameter = new MethodParameter(noQualifiers, 0);
|
||||
NativeWebRequest webRequest = new ServletWebRequest(request);
|
||||
|
||||
new PageableHandlerArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
new PageableHandlerMethodArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@@ -104,7 +108,7 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
MethodParameter parameter = new MethodParameter(invalidQualifiers, 0);
|
||||
NativeWebRequest webRequest = new ServletWebRequest(request);
|
||||
|
||||
new PageableHandlerArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
new PageableHandlerMethodArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -115,8 +119,8 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
assertThat(argument, is(instanceOf(Pageable.class)));
|
||||
|
||||
Pageable pageable = (Pageable) argument;
|
||||
assertThat(pageable.getPageSize(), is(SampleController.DEFAULT_PAGESIZE));
|
||||
assertThat(pageable.getPageNumber(), is(SampleController.DEFAULT_PAGENUMBER));
|
||||
assertThat(pageable.getPageSize(), is(PAGE_SIZE));
|
||||
assertThat(pageable.getPageNumber(), is(PAGE_NUMBER));
|
||||
assertThat(pageable.getSort(), is(nullValue()));
|
||||
}
|
||||
|
||||
@@ -130,12 +134,12 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
|
||||
mockRequest.addParameter("page.page", sizeParam.toString());
|
||||
NativeWebRequest webRequest = new ServletWebRequest(mockRequest);
|
||||
Object argument = new PageableHandlerArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
Object argument = LEGACY.resolveArgument(parameter, null, webRequest, null);
|
||||
|
||||
assertTrue(argument instanceof Pageable);
|
||||
|
||||
Pageable pageable = (Pageable) argument;
|
||||
assertEquals(SampleController.DEFAULT_PAGESIZE, pageable.getPageSize());
|
||||
assertEquals(PAGE_SIZE, pageable.getPageSize());
|
||||
assertEquals(sizeParam - 1, pageable.getPageNumber());
|
||||
}
|
||||
|
||||
@@ -147,9 +151,9 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
assertThat(argument, is(instanceOf(Pageable.class)));
|
||||
|
||||
Pageable pageable = (Pageable) argument;
|
||||
assertThat(pageable.getPageSize(), is(SampleController.DEFAULT_PAGESIZE));
|
||||
assertThat(pageable.getPageNumber(), is(SampleController.DEFAULT_PAGENUMBER));
|
||||
assertThat(pageable.getSort(), is(new Sort("foo")));
|
||||
assertThat(pageable.getPageSize(), is(PAGE_SIZE));
|
||||
assertThat(pageable.getPageNumber(), is(PAGE_NUMBER));
|
||||
assertThat(pageable.getSort(), is(new Sort("firstname", "lastname")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -160,9 +164,20 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
assertThat(argument, is(instanceOf(Pageable.class)));
|
||||
|
||||
Pageable pageable = (Pageable) argument;
|
||||
assertThat(pageable.getPageSize(), is(SampleController.DEFAULT_PAGESIZE));
|
||||
assertThat(pageable.getPageNumber(), is(SampleController.DEFAULT_PAGENUMBER));
|
||||
assertThat(pageable.getSort(), is(new Sort(Direction.DESC, "foo")));
|
||||
assertThat(pageable.getPageSize(), is(PAGE_SIZE));
|
||||
assertThat(pageable.getPageNumber(), is(PAGE_NUMBER));
|
||||
assertThat(pageable.getSort(), is(new Sort(Direction.DESC, "firstname", "lastname")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildsUpRequestParameters() {
|
||||
|
||||
// Set up basic page representation based on 1-indexed page numbers
|
||||
String basicString = String.format("page.page=%d&page.size=%d", PAGE_NUMBER + 1, PAGE_SIZE);
|
||||
|
||||
assertUriStringFor(REFERENCE_WITHOUT_SORT, basicString);
|
||||
assertUriStringFor(REFERENCE_WITH_SORT, basicString + "&page.sort=firstname,lastname&page.sort.dir=desc");
|
||||
assertUriStringFor(REFERENCE_WITH_SORT_FIELDS, basicString + "&page.sort=firstname,lastname&page.sort.dir=asc");
|
||||
}
|
||||
|
||||
private void assertSizeForPrefix(int size, Sort sort, int index) throws Exception {
|
||||
@@ -170,7 +185,7 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
MethodParameter parameter = new MethodParameter(correctMethod, index);
|
||||
NativeWebRequest webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object argument = new PageableHandlerArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
Object argument = LEGACY.resolveArgument(parameter, null, webRequest, null);
|
||||
assertThat(argument, is(instanceOf(Pageable.class)));
|
||||
|
||||
Pageable pageable = (Pageable) argument;
|
||||
@@ -185,43 +200,45 @@ public class PageableHandlerArgumentResolverUnitTests {
|
||||
|
||||
MethodParameter parameter = new MethodParameter(method, 0);
|
||||
NativeWebRequest webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
return new PageableHandlerArgumentResolver().resolveArgument(parameter, null, webRequest, null);
|
||||
|
||||
return LEGACY.resolveArgument(parameter, null, webRequest, null);
|
||||
}
|
||||
|
||||
static class SampleController {
|
||||
@Override
|
||||
protected Class<?> getControllerClass() {
|
||||
return SampleController.class;
|
||||
}
|
||||
|
||||
static final int DEFAULT_PAGESIZE = 198;
|
||||
static final int DEFAULT_PAGENUMBER = 42;
|
||||
@Override
|
||||
protected PageableHandlerMethodArgumentResolver getResolver() {
|
||||
return PageableHandlerMethodArgumentResolver.LEGACY;
|
||||
}
|
||||
|
||||
public void defaultsMethod(
|
||||
@PageableDefaults(value = DEFAULT_PAGESIZE, pageNumber = DEFAULT_PAGENUMBER) Pageable pageable) {
|
||||
static interface SampleController {
|
||||
|
||||
}
|
||||
void simpleDefault(@PageableDefaults(value = PAGE_SIZE, pageNumber = PAGE_NUMBER) Pageable pageable);
|
||||
|
||||
public void defaultsMethodWithSort(
|
||||
@PageableDefaults(value = DEFAULT_PAGESIZE, pageNumber = DEFAULT_PAGENUMBER, sort = "foo") Pageable pageable) {
|
||||
void simpleDefaultWithSort(@PageableDefaults(value = PAGE_SIZE, pageNumber = PAGE_NUMBER, sort = { "firstname",
|
||||
"lastname" }) Pageable pageable);
|
||||
|
||||
}
|
||||
void simpleDefaultWithSortAndDirection(@PageableDefaults(value = PAGE_SIZE, pageNumber = PAGE_NUMBER, sort = {
|
||||
"firstname", "lastname" }, sortDir = Direction.DESC) Pageable pageable);
|
||||
|
||||
public void defaultsMethodWithSortAndDirection(
|
||||
@PageableDefaults(value = DEFAULT_PAGESIZE, pageNumber = DEFAULT_PAGENUMBER, sort = "foo", sortDir = Direction.DESC) Pageable pageable) {
|
||||
void simpleDefaultWithExternalSort(
|
||||
@PageableDefaults(value = PAGE_SIZE, pageNumber = PAGE_NUMBER) @SortDefault(sort = { "firstname", "lastname" }, direction = Direction.DESC) Pageable pageable);
|
||||
|
||||
}
|
||||
void simpleDefaultWithContaineredExternalSort(
|
||||
@PageableDefaults(value = PAGE_SIZE, pageNumber = PAGE_NUMBER) @SortDefaults(@SortDefault(sort = { "firstname",
|
||||
"lastname" }, direction = Direction.DESC)) Pageable pageable);
|
||||
|
||||
public void correctMethod(@Qualifier("foo") Pageable first, @Qualifier("bar") Pageable second) {
|
||||
void correctMethod(@Qualifier("foo") Pageable first, @Qualifier("bar") Pageable second);
|
||||
|
||||
}
|
||||
void invalidQualifiers(@Qualifier("foo") Pageable first, @Qualifier("foo") Pageable second);
|
||||
|
||||
public void failedMethod(Pageable first, Pageable second) {
|
||||
void noQualifiers(Pageable first, Pageable second);
|
||||
|
||||
}
|
||||
void supportedMethod(Pageable pageable);
|
||||
|
||||
public void invalidQualifiers(@Qualifier("foo") Pageable first, @Qualifier("foo") Pageable second) {
|
||||
|
||||
}
|
||||
|
||||
public void otherMethod(String foo) {
|
||||
|
||||
}
|
||||
void unsupportedMethod(String foo);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import org.springframework.web.context.request.ServletWebRequest;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class PageableArgumentResolverUnitTests {
|
||||
|
||||
Method correctMethod, failedMethod, invalidQualifiers, defaultsMethod, defaultsMethodWithSort,
|
||||
@@ -47,7 +48,7 @@ public class PageableArgumentResolverUnitTests {
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
correctMethod = SampleController.class.getMethod("correctMethod", Pageable.class, Pageable.class);
|
||||
failedMethod = SampleController.class.getMethod("failedMethod", Pageable.class, Pageable.class);
|
||||
failedMethod = SampleController.class.getMethod("noQualifiers", Pageable.class, Pageable.class);
|
||||
invalidQualifiers = SampleController.class.getMethod("invalidQualifiers", Pageable.class, Pageable.class);
|
||||
|
||||
defaultsMethod = SampleController.class.getMethod("defaultsMethod", Pageable.class);
|
||||
@@ -206,7 +207,7 @@ public class PageableArgumentResolverUnitTests {
|
||||
|
||||
}
|
||||
|
||||
public void failedMethod(Pageable first, Pageable second) {
|
||||
public void noQualifiers(Pageable first, Pageable second) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.data.web;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.web.SortDefaultUnitTest.*;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Base test class to test supporting of a {@link HandlerMethodArgumentResolver} implementation defaulting
|
||||
* {@link Pageable} method parameters. Expects the {@link HandlerMethodArgumentResolver} to be tested returned from
|
||||
* {@link #getResolver()} and expects methods to be present in the controller class returned from
|
||||
* {@link #getControllerClass()}. For sample usage see {@link PageableHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class PageableDefaultUnitTest {
|
||||
|
||||
static final int PAGE_SIZE = 47;
|
||||
static final int PAGE_NUMBER = 23;
|
||||
|
||||
static final PageRequest REFERENCE_WITHOUT_SORT = new PageRequest(PAGE_NUMBER, PAGE_SIZE);
|
||||
static final PageRequest REFERENCE_WITH_SORT = new PageRequest(PAGE_NUMBER, PAGE_SIZE, SORT);
|
||||
static final PageRequest REFERENCE_WITH_SORT_FIELDS = new PageRequest(PAGE_NUMBER, PAGE_SIZE, new Sort(SORT_FIELDS));
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void supportsPageable() {
|
||||
assertThat(getResolver().supportsParameter(getParameterOfMethod("supportedMethod")), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doesNotSupportNonPageable() {
|
||||
|
||||
MethodParameter parameter = TestUtils.getParameterOfMethod(getControllerClass(), "unsupportedMethod", String.class);
|
||||
assertThat(getResolver().supportsParameter(parameter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsDefaultIfNoRequestParametersAndNoDefault() throws Exception {
|
||||
assertSupportedAndResult(getParameterOfMethod("supportedMethod"),
|
||||
(Pageable) ReflectionTestUtils.getField(getResolver(), "fallbackPageable"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleDefault() throws Exception {
|
||||
assertSupportedAndResult(getParameterOfMethod("simpleDefault"), REFERENCE_WITHOUT_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleDefaultWithSort() throws Exception {
|
||||
assertSupportedAndResult(getParameterOfMethod("simpleDefaultWithSort"), REFERENCE_WITH_SORT_FIELDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleDefaultWithSortAndDirection() throws Exception {
|
||||
assertSupportedAndResult(getParameterOfMethod("simpleDefaultWithSortAndDirection"), REFERENCE_WITH_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleDefaultWithExternalSort() throws Exception {
|
||||
assertSupportedAndResult(getParameterOfMethod("simpleDefaultWithExternalSort"), REFERENCE_WITH_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simpleDefaultWithContaineredExternalSort() throws Exception {
|
||||
assertSupportedAndResult(getParameterOfMethod("simpleDefaultWithContaineredExternalSort"), REFERENCE_WITH_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsInvalidQulifiers() throws Exception {
|
||||
|
||||
MethodParameter parameter = TestUtils.getParameterOfMethod(getControllerClass(), "invalidQualifiers",
|
||||
Pageable.class, Pageable.class);
|
||||
|
||||
HandlerMethodArgumentResolver resolver = getResolver();
|
||||
assertThat(resolver.supportsParameter(parameter), is(true));
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectMessage("unique");
|
||||
|
||||
resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsNoQualifiers() throws Exception {
|
||||
|
||||
MethodParameter parameter = TestUtils.getParameterOfMethod(getControllerClass(), "noQualifiers", Pageable.class,
|
||||
Pageable.class);
|
||||
|
||||
HandlerMethodArgumentResolver resolver = getResolver();
|
||||
assertThat(resolver.supportsParameter(parameter), is(true));
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectMessage("Ambiguous");
|
||||
|
||||
resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null);
|
||||
}
|
||||
|
||||
private void assertSupportedAndResult(MethodParameter parameter, Pageable pageable) throws Exception {
|
||||
|
||||
HandlerMethodArgumentResolver resolver = getResolver();
|
||||
assertThat(resolver.supportsParameter(parameter), is(true));
|
||||
assertThat(resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null), is((Object) pageable));
|
||||
}
|
||||
|
||||
protected void assertUriStringFor(Pageable pageable, String expected) {
|
||||
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/");
|
||||
MethodParameter parameter = getParameterOfMethod("supportedMethod");
|
||||
|
||||
getResolver().enhance(builder, parameter, pageable);
|
||||
|
||||
assertThat(builder.build().toUriString(), endsWith(expected));
|
||||
}
|
||||
|
||||
protected abstract PageableHandlerMethodArgumentResolver getResolver();
|
||||
|
||||
protected abstract Class<?> getControllerClass();
|
||||
|
||||
protected MethodParameter getParameterOfMethod(String name) {
|
||||
return getParameterOfMethod(getControllerClass(), name);
|
||||
}
|
||||
|
||||
private static MethodParameter getParameterOfMethod(Class<?> controller, String name) {
|
||||
return TestUtils.getParameterOfMethod(controller, name, Pageable.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.data.web;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.web.SortDefault.SortDefaults;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PageableHandlerMethodArgumentResolver}. Pulls in defaulting tests from
|
||||
* {@link PageableDefaultUnitTest}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class PageableHandlerMethodArgumentResolverUnitTest extends PageableDefaultUnitTest {
|
||||
|
||||
@Test
|
||||
public void buildsUpRequestParameters() {
|
||||
|
||||
String basicString = String.format("page=%d&size=%d", PAGE_NUMBER, PAGE_SIZE);
|
||||
|
||||
assertUriStringFor(REFERENCE_WITHOUT_SORT, basicString);
|
||||
assertUriStringFor(REFERENCE_WITH_SORT, basicString + "&sort=firstname,lastname,desc");
|
||||
assertUriStringFor(REFERENCE_WITH_SORT_FIELDS, basicString + "&sort=firstname,lastname,asc");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PageableHandlerMethodArgumentResolver getResolver() {
|
||||
return new PageableHandlerMethodArgumentResolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getControllerClass() {
|
||||
return Sample.class;
|
||||
}
|
||||
|
||||
interface Sample {
|
||||
|
||||
void supportedMethod(Pageable pageable);
|
||||
|
||||
void unsupportedMethod(String string);
|
||||
|
||||
void simpleDefault(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER) Pageable pageable);
|
||||
|
||||
void simpleDefaultWithSort(
|
||||
@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER, sort = { "firstname", "lastname" }) Pageable pageable);
|
||||
|
||||
void simpleDefaultWithSortAndDirection(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER, sort = { "firstname",
|
||||
"lastname" }, direction = Direction.DESC) Pageable pageable);
|
||||
|
||||
void simpleDefaultWithExternalSort(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER)//
|
||||
@SortDefault(sort = { "firstname", "lastname" }, direction = Direction.DESC) Pageable pageable);
|
||||
|
||||
void simpleDefaultWithContaineredExternalSort(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER)//
|
||||
@SortDefaults(@SortDefault(sort = { "firstname", "lastname" }, direction = Direction.DESC)) Pageable pageable);
|
||||
|
||||
void invalidQualifiers(@Qualifier("foo") Pageable first, @Qualifier("foo") Pageable second);
|
||||
|
||||
void noQualifiers(Pageable first, Pageable second);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.data.web;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.domain.Sort.Direction.*;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.core.MethodParameter;
|
||||
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.web.method.support.HandlerMethodArgumentResolver;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SortDefault}.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public abstract class SortDefaultUnitTest {
|
||||
|
||||
static final String SORT_0 = "username";
|
||||
static final String SORT_1 = "username,asc";
|
||||
static final String[] SORT_2 = new String[] { "username,ASC", "lastname,firstname,DESC" };
|
||||
static final String SORT_3 = "firstname,lastname";
|
||||
|
||||
static final String[] SORT_FIELDS = new String[] { "firstname", "lastname" };
|
||||
static final Direction SORT_DIRECTION = Direction.DESC;
|
||||
|
||||
static final Sort SORT = new Sort(SORT_DIRECTION, SORT_FIELDS);
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Test
|
||||
public void parsesSimpleSortStringCorrectly() {
|
||||
|
||||
assertSortStringParsedInto(new Sort(new Order("username")), SORT_1);
|
||||
assertSortStringParsedInto(new Sort(new Order(ASC, "username")), SORT_1);
|
||||
assertSortStringParsedInto(new Sort(new Order(ASC, "username"), //
|
||||
new Order(DESC, "lastname"), new Order(DESC, "firstname")), SORT_2);
|
||||
assertSortStringParsedInto(new Sort("firstname", "lastname"), SORT_3);
|
||||
}
|
||||
|
||||
private static void assertSortStringParsedInto(Sort expected, String... source) {
|
||||
|
||||
SortHandlerMethodArgumentResolver resolver = new SortHandlerMethodArgumentResolver();
|
||||
Sort sort = resolver.parseParameterIntoSort(source, ",");
|
||||
|
||||
assertThat(sort, is(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsSortParameter() {
|
||||
assertThat(getResolver().supportsParameter(getParameterOfMethod("supportedMethod")), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullForNoDefault() throws Exception {
|
||||
assertSupportedAndResolvedTo(getParameterOfMethod("supportedMethod"), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversSimpleDefault() throws Exception {
|
||||
assertSupportedAndResolvedTo(getParameterOfMethod("simpleDefault"), new Sort(Direction.ASC, SORT_FIELDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversSimpleDefaultWithDirection() throws Exception {
|
||||
assertSupportedAndResolvedTo(getParameterOfMethod("simpleDefaultWithDirection"), SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsNonSortParameter() {
|
||||
|
||||
MethodParameter parameter = TestUtils.getParameterOfMethod(getControllerClass(), "unsupportedMethod", String.class);
|
||||
assertThat(getResolver().supportsParameter(parameter), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectsDoubleAnnotatedMethod() throws Exception {
|
||||
|
||||
MethodParameter parameter = getParameterOfMethod("invalid");
|
||||
|
||||
HandlerMethodArgumentResolver resolver = new SortHandlerMethodArgumentResolver();
|
||||
assertThat(resolver.supportsParameter(parameter), is(true));
|
||||
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectMessage(SortDefault.class.getSimpleName());
|
||||
exception.expectMessage(SortDefaults.class.getSimpleName());
|
||||
exception.expectMessage(parameter.toString());
|
||||
|
||||
resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversContaineredDefault() throws Exception {
|
||||
|
||||
MethodParameter parameter = getParameterOfMethod("containeredDefault");
|
||||
Sort reference = new Sort("foo", "bar");
|
||||
|
||||
assertSupportedAndResolvedTo(parameter, reference);
|
||||
}
|
||||
|
||||
protected HandlerMethodArgumentResolver getResolver() {
|
||||
return new SortHandlerMethodArgumentResolver();
|
||||
}
|
||||
|
||||
protected abstract Class<?> getControllerClass();
|
||||
|
||||
private void assertSupportedAndResolvedTo(MethodParameter parameter, Sort sort) throws Exception {
|
||||
|
||||
HandlerMethodArgumentResolver resolver = getResolver();
|
||||
assertThat(resolver.supportsParameter(parameter), is(true));
|
||||
assertThat(resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null), is((Object) sort));
|
||||
}
|
||||
|
||||
protected MethodParameter getParameterOfMethod(String name) {
|
||||
return getParameterOfMethod(getControllerClass(), name);
|
||||
}
|
||||
|
||||
private static MethodParameter getParameterOfMethod(Class<?> controller, String name) {
|
||||
return TestUtils.getParameterOfMethod(controller, name, Sort.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.data.web;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.domain.Sort.Direction.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.MethodParameter;
|
||||
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.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SortHandlerMethodArgumentResolver}.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SortHandlerArgumentResolverUnitTests extends SortDefaultUnitTest {
|
||||
|
||||
static final String SORT_0 = "username";
|
||||
static final String SORT_1 = "username,asc";
|
||||
static final String[] SORT_2 = new String[] { "username,ASC", "lastname,firstname,DESC" };
|
||||
static final String SORT_3 = "firstname,lastname";
|
||||
|
||||
@Test
|
||||
public void discoversSimpleSortFromRequest() {
|
||||
|
||||
MethodParameter parameter = getParameterOfMethod("simpleDefault");
|
||||
Sort reference = new Sort("bar", "foo");
|
||||
NativeWebRequest request = getRequestWithSort(reference);
|
||||
|
||||
assertSupportedAndResolvedTo(request, parameter, reference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversComplexSortFromRequest() {
|
||||
|
||||
MethodParameter parameter = getParameterOfMethod("simpleDefault");
|
||||
Sort reference = new Sort("bar", "foo").and(new Sort("fizz", "buzz"));
|
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithSort(reference), parameter, reference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoversQualifiedSortFromRequest() {
|
||||
|
||||
MethodParameter parameter = getParameterOfMethod("qualifiedSort");
|
||||
Sort reference = new Sort("bar", "foo");
|
||||
|
||||
assertSupportedAndResolvedTo(getRequestWithSort(reference, "qual"), parameter, reference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsNullForSortParameterSetToNothing() throws Exception {
|
||||
|
||||
MethodParameter parameter = getParameterOfMethod("supportedMethod");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("sort", (String) null);
|
||||
|
||||
SortHandlerMethodArgumentResolver resolver = new SortHandlerMethodArgumentResolver();
|
||||
Sort result = resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null);
|
||||
assertThat(result, is(nullValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildsUpRequestParameters() {
|
||||
assertUriStringFor(SORT, "sort=firstname,lastname,desc");
|
||||
assertUriStringFor(new Sort(ASC, "foo").and(new Sort(DESC, "bar").and(new Sort(ASC, "foobar"))),
|
||||
"sort=foo,asc&sort=bar,desc&sort=foobar,asc");
|
||||
assertUriStringFor(new Sort(ASC, "foo").and(new Sort(ASC, "bar").and(new Sort(DESC, "foobar"))),
|
||||
"sort=foo,bar,asc&sort=foobar,desc");
|
||||
}
|
||||
|
||||
private void assertUriStringFor(Sort sort, String expected) {
|
||||
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/");
|
||||
MethodParameter parameter = getParameterOfMethod("supportedMethod");
|
||||
|
||||
new SortHandlerMethodArgumentResolver().enhance(builder, parameter, sort);
|
||||
|
||||
assertThat(builder.build().toUriString(), endsWith(expected));
|
||||
}
|
||||
|
||||
private static void assertSupportedAndResolvedTo(NativeWebRequest request, MethodParameter parameter, Sort sort) {
|
||||
|
||||
SortHandlerMethodArgumentResolver resolver = new SortHandlerMethodArgumentResolver();
|
||||
assertThat(resolver.supportsParameter(parameter), is(true));
|
||||
|
||||
try {
|
||||
assertThat(resolver.resolveArgument(parameter, null, request, null), is(sort));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static NativeWebRequest getRequestWithSort(Sort sort) {
|
||||
|
||||
return getRequestWithSort(sort, null);
|
||||
}
|
||||
|
||||
private static NativeWebRequest getRequestWithSort(Sort sort, String qualifier) {
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
if (sort == null) {
|
||||
return new ServletWebRequest(request);
|
||||
}
|
||||
|
||||
for (Order order : sort) {
|
||||
|
||||
String prefix = StringUtils.hasText(qualifier) ? qualifier + "_" : "";
|
||||
request.addParameter(prefix + "sort", String.format("%s,%s", order.getProperty(), order.getDirection().name()));
|
||||
}
|
||||
|
||||
return new ServletWebRequest(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getControllerClass() {
|
||||
return Controller.class;
|
||||
}
|
||||
|
||||
interface Controller {
|
||||
|
||||
void supportedMethod(Sort sort);
|
||||
|
||||
void unsupportedMethod(String string);
|
||||
|
||||
void qualifiedSort(@Qualifier("qual") Sort sort);
|
||||
|
||||
void simpleDefault(@SortDefault({ "firstname", "lastname" }) Sort sort);
|
||||
|
||||
void simpleDefaultWithDirection(
|
||||
@SortDefault(sort = { "firstname", "lastname" }, direction = Direction.DESC) Sort sort);
|
||||
|
||||
void containeredDefault(@SortDefaults(@SortDefault({ "foo", "bar" })) Sort sort);
|
||||
|
||||
void invalid(@SortDefaults(@SortDefault({ "foo", "bar" })) @SortDefault({ "bar", "foo" }) Sort sort);
|
||||
}
|
||||
}
|
||||
51
src/test/java/org/springframework/data/web/TestUtils.java
Normal file
51
src/test/java/org/springframework/data/web/TestUtils.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 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.
|
||||
* 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.data.web;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* General test utilities.
|
||||
*
|
||||
* @since 1.6
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
class TestUtils {
|
||||
|
||||
public static NativeWebRequest getWebRequest() {
|
||||
return new ServletWebRequest(new MockHttpServletRequest());
|
||||
}
|
||||
|
||||
public static MethodParameter getParameterOfMethod(Class<?> controller, String name, Class<?>... argumentTypes) {
|
||||
|
||||
Method method = getMethod(controller, name, argumentTypes);
|
||||
return new MethodParameter(method, 0);
|
||||
}
|
||||
|
||||
public static Method getMethod(Class<?> controller, String name, Class<?>... argumentTypes) {
|
||||
|
||||
try {
|
||||
return controller.getMethod(name, argumentTypes);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user