Skip to content

Commit e11efed

Browse files
committed
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.
1 parent ed32d83 commit e11efed

16 files changed

+1619
-438
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<properties>
2020
<jackson>1.9.7</jackson>
2121
<querydsl>2.8.0</querydsl>
22-
<springhateoas>0.4.0.RELEASE</springhateoas>
22+
<springhateoas>0.5.0.BUILD-SNAPSHOT</springhateoas>
2323
<dist.key>DATACMNS</dist.key>
2424
</properties>
2525

src/main/java/org/springframework/data/web/PageableArgumentResolver.java

Lines changed: 3 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
*/
1616
package org.springframework.data.web;
1717

18+
import static org.springframework.data.web.SpringDataAnnotationUtils.*;
19+
1820
import java.beans.PropertyEditorSupport;
1921
import java.lang.annotation.Annotation;
20-
import java.lang.reflect.Method;
21-
import java.util.HashSet;
22-
import java.util.Set;
2322

2423
import javax.servlet.ServletRequest;
2524

@@ -131,7 +130,7 @@ private Pageable getDefaultFromAnnotationOrFallback(MethodParameter methodParame
131130
return new PageRequest(fallbackPagable.getPageNumber(), fallbackPagable.getPageSize(), fallbackPagable.getSort());
132131
}
133132

134-
private static Pageable getDefaultPageRequestFrom(PageableDefaults defaults) {
133+
static Pageable getDefaultPageRequestFrom(PageableDefaults defaults) {
135134

136135
// +1 is because we substract 1 later
137136
int defaultPageNumber = defaults.pageNumber() + 1;
@@ -162,94 +161,6 @@ private String getPrefix(MethodParameter parameter) {
162161
return prefix;
163162
}
164163

165-
/**
166-
* Asserts uniqueness of all {@link Pageable} parameters of the method of the given {@link MethodParameter}.
167-
*
168-
* @param parameter
169-
*/
170-
private void assertPageableUniqueness(MethodParameter parameter) {
171-
172-
Method method = parameter.getMethod();
173-
174-
if (containsMoreThanOnePageableParameter(method)) {
175-
Annotation[][] annotations = method.getParameterAnnotations();
176-
assertQualifiersFor(method.getParameterTypes(), annotations);
177-
}
178-
}
179-
180-
/**
181-
* Returns whether the given {@link Method} has more than one {@link Pageable} parameter.
182-
*
183-
* @param method
184-
* @return
185-
*/
186-
private boolean containsMoreThanOnePageableParameter(Method method) {
187-
188-
boolean pageableFound = false;
189-
190-
for (Class<?> type : method.getParameterTypes()) {
191-
192-
if (pageableFound && type.equals(Pageable.class)) {
193-
return true;
194-
}
195-
196-
if (type.equals(Pageable.class)) {
197-
pageableFound = true;
198-
}
199-
}
200-
201-
return false;
202-
}
203-
204-
/**
205-
* Asserts that every {@link Pageable} parameter of the given parameters carries an {@link Qualifier} annotation to
206-
* distinguish them from each other.
207-
*
208-
* @param parameterTypes
209-
* @param annotations
210-
*/
211-
private void assertQualifiersFor(Class<?>[] parameterTypes, Annotation[][] annotations) {
212-
213-
Set<String> values = new HashSet<String>();
214-
215-
for (int i = 0; i < annotations.length; i++) {
216-
217-
if (Pageable.class.equals(parameterTypes[i])) {
218-
219-
Qualifier qualifier = findAnnotation(annotations[i]);
220-
221-
if (null == qualifier) {
222-
throw new IllegalStateException(
223-
"Ambiguous Pageable arguments in handler method. If you use multiple parameters of type Pageable you need to qualify them with @Qualifier");
224-
}
225-
226-
if (values.contains(qualifier.value())) {
227-
throw new IllegalStateException("Values of the user Qualifiers must be unique!");
228-
}
229-
230-
values.add(qualifier.value());
231-
}
232-
}
233-
}
234-
235-
/**
236-
* Returns a {@link Qualifier} annotation from the given array of {@link Annotation}s. Returns {@literal null} if the
237-
* array does not contain a {@link Qualifier} annotation.
238-
*
239-
* @param annotations
240-
* @return
241-
*/
242-
private Qualifier findAnnotation(Annotation[] annotations) {
243-
244-
for (Annotation annotation : annotations) {
245-
if (annotation instanceof Qualifier) {
246-
return (Qualifier) annotation;
247-
}
248-
}
249-
250-
return null;
251-
}
252-
253164
/**
254165
* {@link java.beans.PropertyEditor} to create {@link Sort} instances from textual representations. The implementation
255166
* interprets the string as a comma separated list where the first entry is the sort direction ( {@code asc},
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.web;
17+
18+
import java.lang.annotation.Documented;
19+
import java.lang.annotation.ElementType;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
22+
import java.lang.annotation.Target;
23+
24+
import org.springframework.data.domain.Sort.Direction;
25+
import org.springframework.data.web.SortDefault.SortDefaults;
26+
27+
/**
28+
* Annotation to set defaults when injecting a {@link org.springframework.data.domain.Pageable} into a controller
29+
* method. Instead of configuring {@link #sort()} and {@link #direction()} you can also use {@link SortDefault} or
30+
* {@link SortDefaults}.
31+
*
32+
* @since 1.6
33+
* @author Oliver Gierke
34+
*/
35+
@Documented
36+
@Retention(RetentionPolicy.RUNTIME)
37+
@Target(ElementType.PARAMETER)
38+
public @interface PageableDefault {
39+
40+
/**
41+
* Alias for {@link #size()}. Prefer to use the {@link #size()} method as it makes the annotation declaration more
42+
* expressive and you'll probably want to configure the {@link #page()} anyway.
43+
*
44+
* @return
45+
*/
46+
int value() default 10;
47+
48+
/**
49+
* The default-size the injected {@link org.springframework.data.domain.Pageable} should get if no corresponding
50+
* parameter defined in request (default is 10).
51+
*/
52+
int size() default 10;
53+
54+
/**
55+
* The default-pagenumber the injected {@link org.springframework.data.domain.Pageable} should get if no corresponding
56+
* parameter defined in request (default is 0).
57+
*/
58+
int page() default 0;
59+
60+
/**
61+
* The properties to sort by by default. If unset, no sorting will be applied at all.
62+
*
63+
* @return
64+
*/
65+
String[] sort() default {};
66+
67+
/**
68+
* The direction to sort by. Defaults to {@link Direction#ASC}.
69+
*
70+
* @return
71+
*/
72+
Direction direction() default Direction.ASC;
73+
}

src/main/java/org/springframework/data/web/PageableDefaults.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.springframework.data.web;
1717

18+
import java.lang.annotation.Documented;
1819
import java.lang.annotation.ElementType;
1920
import java.lang.annotation.Retention;
2021
import java.lang.annotation.RetentionPolicy;
@@ -26,10 +27,13 @@
2627
* Annotation to set defaults when injecting a {@link org.springframework.data.domain.Pageable} into a controller
2728
* method.
2829
*
30+
* @deprecated use {@link PageableDefault} instead.
2931
* @author Oliver Gierke
3032
*/
33+
@Documented
3134
@Retention(RetentionPolicy.RUNTIME)
3235
@Target(ElementType.PARAMETER)
36+
@Deprecated
3337
public @interface PageableDefaults {
3438

3539
/**

0 commit comments

Comments
 (0)