18
18
import static org .assertj .core .api .Assertions .*;
19
19
import static org .springframework .data .web .querydsl .QuerydslPredicateArgumentResolver .*;
20
20
21
+ import java .lang .annotation .ElementType ;
22
+ import java .lang .annotation .Retention ;
23
+ import java .lang .annotation .RetentionPolicy ;
24
+ import java .lang .annotation .Target ;
21
25
import java .util .Optional ;
22
26
23
27
import org .junit .jupiter .api .BeforeEach ;
24
28
import org .junit .jupiter .api .Test ;
25
29
import org .springframework .core .MethodParameter ;
30
+ import org .springframework .core .annotation .AliasFor ;
31
+ import org .springframework .core .annotation .MergedAnnotation ;
26
32
import org .springframework .data .domain .Page ;
27
33
import org .springframework .data .domain .Pageable ;
28
34
import org .springframework .data .querydsl .QUser ;
@@ -149,6 +155,20 @@ void resolveArgumentShouldHonorCustomSpecification() throws Exception {
149
155
QUser .user .firstname .eq ("egwene" .toUpperCase ()).and (QUser .user .lastname .toLowerCase ().eq ("al'vere" )));
150
156
}
151
157
158
+ @ Test // #2277
159
+ void resolveArgumentShouldHonorMetaAnnotation () throws Exception {
160
+
161
+ request .addParameter ("firstname" , "egwene" );
162
+ request .addParameter ("lastname" , "al'vere" );
163
+
164
+ Object predicate = resolver .resolveArgument (
165
+ getMethodParameterFor ("specificFindWithMetaAnnotation" , Predicate .class ), null , new ServletWebRequest (request ),
166
+ null );
167
+
168
+ assertThat (predicate ).isEqualTo (
169
+ QUser .user .firstname .eq ("egwene" .toUpperCase ()).and (QUser .user .lastname .toLowerCase ().eq ("al'vere" )));
170
+ }
171
+
152
172
@ Test // DATACMNS-669
153
173
void shouldCreatePredicateForNonStringPropertyCorrectly () throws Exception {
154
174
@@ -188,7 +208,7 @@ void shouldExcludePropertiesCorrectly() throws Exception {
188
208
void extractTypeInformationShouldUseTypeExtractedFromMethodReturnTypeIfPredicateNotAnnotated () {
189
209
190
210
TypeInformation <?> type = ReflectionTestUtils .invokeMethod (resolver , "extractTypeInfo" ,
191
- getMethodParameterFor ("predicateWithoutAnnotation" , Predicate .class ));
211
+ getMethodParameterFor ("predicateWithoutAnnotation" , Predicate .class ), MergedAnnotation . missing () );
192
212
193
213
assertThat (type ).isEqualTo (ClassTypeInformation .from (User .class ));
194
214
}
@@ -200,9 +220,11 @@ void detectsDomainTypesCorrectly() {
200
220
TypeInformation USER_TYPE = ClassTypeInformation .from (User .class );
201
221
TypeInformation MODELA_AND_VIEW_TYPE = ClassTypeInformation .from (ModelAndView .class );
202
222
203
- assertThat (extractTypeInfo (getMethodParameterFor ("forEntity" ))).isEqualTo (USER_TYPE );
204
- assertThat (extractTypeInfo (getMethodParameterFor ("forResourceOfUser" ))).isEqualTo (USER_TYPE );
205
- assertThat (extractTypeInfo (getMethodParameterFor ("forModelAndView" ))).isEqualTo (MODELA_AND_VIEW_TYPE );
223
+ assertThat (extractTypeInfo (getMethodParameterFor ("forEntity" ), MergedAnnotation .missing ())).isEqualTo (USER_TYPE );
224
+ assertThat (extractTypeInfo (getMethodParameterFor ("forResourceOfUser" ), MergedAnnotation .missing ()))
225
+ .isEqualTo (USER_TYPE );
226
+ assertThat (extractTypeInfo (getMethodParameterFor ("forModelAndView" ), MergedAnnotation .missing ()))
227
+ .isEqualTo (MODELA_AND_VIEW_TYPE );
206
228
}
207
229
208
230
@ Test // DATACMNS-1593
@@ -276,6 +298,8 @@ static interface Sample {
276
298
277
299
User specificFind (@ QuerydslPredicate (bindings = SpecificBinding .class ) Predicate predicate );
278
300
301
+ User specificFindWithMetaAnnotation (@ MyQuerydslPredicate Predicate predicate );
302
+
279
303
HttpEntity <User > forEntity ();
280
304
281
305
ModelAndView forModelAndView ();
@@ -296,4 +320,23 @@ public void customize(QuerydslBindings bindings, QUser user) {
296
320
bindings .bind (QUser .user .firstname ).first ((path , value ) -> path .contains (value ));
297
321
}
298
322
}
323
+
324
+ @ Target ({ ElementType .PARAMETER , ElementType .TYPE })
325
+ @ Retention (RetentionPolicy .RUNTIME )
326
+ @ QuerydslPredicate
327
+ public @interface MyQuerydslPredicate {
328
+
329
+ /**
330
+ * To customize the way individual properties' values should be bound to the predicate a
331
+ * {@link QuerydslBinderCustomizer} can be specified here. We'll try to obtain a Spring bean of this type but fall
332
+ * back to a plain instantiation if no bean is found in the current
333
+ * {@link org.springframework.beans.factory.BeanFactory}.
334
+ *
335
+ * @return
336
+ */
337
+ @ SuppressWarnings ("rawtypes" )
338
+ @ AliasFor (annotation = QuerydslPredicate .class , attribute = "bindings" )
339
+ Class <? extends QuerydslBinderCustomizer > bindings () default SpecificBinding .class ;
340
+ }
341
+
299
342
}
0 commit comments