DATACMNS-1593, DATACMNS-1635 - Overhauled null handling in QuerydslPredicateArgumentResolver.
QuerydslPredicateArgumentResolver now properly handles predicate lookups that result in null values. The semantics of a handler method parameter of type of Querydsl's Predicate have been tightened to always see a non-null Predicate by default. Users that want to handle the absence of predicates explicitly can opt into seeing null by annotating the parameter with @Nullable or use Optional<Predicate>. QuerydslPredicateBuilder now consistently returns null in case the original parameter map is entirely empty or consists of only keys with empty value arrays as empty form submissions do. This partially reverts the work of DATACMNS-1168, which moved into the direction of returning a default Predicate value for empty maps in the first place. That however prevents us from producing empty Optionals. Related tickets: DATACMNS-1168.
This commit is contained in:
@@ -22,7 +22,6 @@ import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -38,6 +37,7 @@ import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
@@ -94,7 +94,7 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
|
||||
request.addParameter("firstname", "rand");
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate).isEqualTo(QUser.user.firstname.eq("rand"));
|
||||
@@ -106,7 +106,7 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
request.addParameter("firstname", "rand");
|
||||
request.addParameter("lastname", "al'thor");
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate).isEqualTo(QUser.user.firstname.eq("rand").and(QUser.user.lastname.eq("al'thor")));
|
||||
@@ -117,12 +117,12 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
|
||||
request.addParameter("address.city", "two rivers");
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("simpleFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
BooleanExpression eq = QUser.user.address.city.eq("two rivers");
|
||||
|
||||
assertThat(predicate).isEqualTo((Predicate) eq);
|
||||
assertThat(predicate).isEqualTo(eq);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-669
|
||||
@@ -130,10 +130,10 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
|
||||
request.addParameter("address.city", "tar valon");
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("pagedFind", Predicate.class, Pageable.class),
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("pagedFind", Predicate.class, Pageable.class),
|
||||
null, new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate).isEqualTo((Predicate) QUser.user.address.city.eq("tar valon"));
|
||||
assertThat(predicate).isEqualTo(QUser.user.address.city.eq("tar valon"));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-669
|
||||
@@ -142,7 +142,7 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
request.addParameter("firstname", "egwene");
|
||||
request.addParameter("lastname", "al'vere");
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate).isEqualTo(
|
||||
@@ -154,10 +154,10 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
|
||||
request.addParameter("inceptionYear", "978");
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate).isEqualTo((Predicate) QUser.user.inceptionYear.eq(978L));
|
||||
assertThat(predicate).isEqualTo(QUser.user.inceptionYear.eq(978L));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-669
|
||||
@@ -165,10 +165,10 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
|
||||
request.addParameter("inceptionYear", new String[] { "978", "998" });
|
||||
|
||||
Predicate predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
Object predicate = resolver.resolveArgument(getMethodParameterFor("specificFind", Predicate.class), null,
|
||||
new ServletWebRequest(request), null);
|
||||
|
||||
assertThat(predicate).isEqualTo((Predicate) QUser.user.inceptionYear.in(978L, 998L));
|
||||
assertThat(predicate).isEqualTo(QUser.user.inceptionYear.in(978L, 998L));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-669
|
||||
@@ -190,7 +190,7 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
TypeInformation<?> type = ReflectionTestUtils.invokeMethod(resolver, "extractTypeInfo",
|
||||
getMethodParameterFor("predicateWithoutAnnotation", Predicate.class));
|
||||
|
||||
assertThat(type).isEqualTo((TypeInformation) ClassTypeInformation.from(User.class));
|
||||
assertThat(type).isEqualTo(ClassTypeInformation.from(User.class));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-669
|
||||
@@ -205,6 +205,43 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
assertThat(extractTypeInfo(getMethodParameterFor("forModelAndView"))).isEqualTo(MODELA_AND_VIEW_TYPE);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1593
|
||||
public void returnsEmptyPredicateForEmptyInput() throws Exception {
|
||||
|
||||
MethodParameter parameter = getMethodParameterFor("predicateWithoutAnnotation", Predicate.class);
|
||||
|
||||
request.addParameter("firstname", "");
|
||||
|
||||
assertThat(resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null)) //
|
||||
.isNotNull();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1635
|
||||
public void forwardsNullValueForNullablePredicate() throws Exception {
|
||||
|
||||
MethodParameter parameter = getMethodParameterFor("nullablePredicateWithoutAnnotation", Predicate.class);
|
||||
|
||||
request.addParameter("firstname", "");
|
||||
|
||||
assertThat(resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null)).isNull();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1635
|
||||
public void returnsOptionalIfDeclared() throws Exception {
|
||||
|
||||
MethodParameter parameter = getMethodParameterFor("optionalPredicateWithoutAnnotation", Optional.class);
|
||||
|
||||
request.addParameter("firstname", "");
|
||||
|
||||
assertThat(resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null)) //
|
||||
.isInstanceOfSatisfying(Optional.class, it -> assertThat(it).isEmpty());
|
||||
|
||||
request.addParameter("lastname", "Matthews");
|
||||
|
||||
assertThat(resolver.resolveArgument(parameter, null, new ServletWebRequest(request), null)) //
|
||||
.isInstanceOfSatisfying(Optional.class, it -> assertThat(it).isPresent());
|
||||
}
|
||||
|
||||
private static MethodParameter getMethodParameterFor(String methodName, Class<?>... args) throws RuntimeException {
|
||||
|
||||
try {
|
||||
@@ -244,6 +281,12 @@ public class QuerydslPredicateArgumentResolverUnitTests {
|
||||
ModelAndView forModelAndView();
|
||||
|
||||
ResponseEntity<EntityModel<User>> forResourceOfUser();
|
||||
|
||||
// Nullability
|
||||
|
||||
User nullablePredicateWithoutAnnotation(@Nullable Predicate predicate);
|
||||
|
||||
User optionalPredicateWithoutAnnotation(Optional<Predicate> predicate);
|
||||
}
|
||||
|
||||
public static class SampleRepo implements QuerydslBinderCustomizer<QUser> {
|
||||
|
||||
Reference in New Issue
Block a user