DATACMNS-1762 - Reintroduce calls to ReactiveWrapperConverters.supports(…) after decoupling from QueryExecutionConverters.
We now consider reactive wrapper types in all areas that previously relied on QueryExecutionConverters to handle reactive type information correctly. Specifically, we call supports(…) and perform type unwrapping to ensure to detect the correct return type.
This commit is contained in:
@@ -109,11 +109,7 @@ public abstract class AbstractRepositoryMetadata implements RepositoryMetadata {
|
||||
|
||||
TypeInformation<?> returnType = getReturnType(method);
|
||||
|
||||
if (ReactiveWrapperConverters.supports(returnType.getType())) {
|
||||
return ReactiveWrapperConverters.unwrapWrapperTypes(returnType).getType();
|
||||
}
|
||||
|
||||
return ReactiveWrapperConverters.unwrapWrapperTypes(QueryExecutionConverters.unwrapWrapperTypes(returnType))
|
||||
return QueryExecutionConverters.unwrapWrapperTypes(ReactiveWrapperConverters.unwrapWrapperTypes(returnType))
|
||||
.getType();
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,8 @@ class QueryExecutionResultHandler {
|
||||
|
||||
result = unwrapOptional(result);
|
||||
|
||||
if (QueryExecutionConverters.supports(expectedReturnType)) {
|
||||
if (QueryExecutionConverters.supports(expectedReturnType)
|
||||
|| ReactiveWrapperConverters.supports(expectedReturnType)) {
|
||||
|
||||
// For a wrapper type, try nested resolution first
|
||||
result = postProcessInvocationResult(result, nestingLevel + 1, descriptor);
|
||||
|
||||
@@ -230,7 +230,7 @@ public class Parameter {
|
||||
TypeInformation<Object> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
|
||||
return bound
|
||||
.equals(ReactiveWrapperConverters.unwrapWrapperTypes(QueryExecutionConverters.unwrapWrapperTypes(returnType)));
|
||||
.equals(QueryExecutionConverters.unwrapWrapperTypes(ReactiveWrapperConverters.unwrapWrapperTypes(returnType)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Optional;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.util.QueryExecutionConverters;
|
||||
import org.springframework.data.repository.util.ReactiveWrapperConverters;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -64,7 +65,8 @@ public class ParametersParameterAccessor implements ParameterAccessor {
|
||||
private static boolean requiresUnwrapping(Object[] values) {
|
||||
|
||||
for (Object value : values) {
|
||||
if (value != null && QueryExecutionConverters.supports(value.getClass())) {
|
||||
if (value != null && (QueryExecutionConverters.supports(value.getClass())
|
||||
|| ReactiveWrapperConverters.supports(value.getClass()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.util.QueryExecutionConverters;
|
||||
import org.springframework.data.repository.util.ReactiveWrapperConverters;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
@@ -271,7 +272,8 @@ public class QueryMethod {
|
||||
private static Class<? extends Object> potentiallyUnwrapReturnTypeFor(RepositoryMetadata metadata, Method method) {
|
||||
|
||||
TypeInformation<?> returnType = metadata.getReturnType(method);
|
||||
if (QueryExecutionConverters.supports(returnType.getType())) {
|
||||
if (QueryExecutionConverters.supports(returnType.getType())
|
||||
|| ReactiveWrapperConverters.supports(returnType.getType())) {
|
||||
|
||||
// unwrap only one level to handle cases like Future<List<Entity>> correctly.
|
||||
|
||||
|
||||
@@ -187,6 +187,8 @@ public abstract class ClassUtils {
|
||||
private static TypeInformation<?> getEffectivelyReturnedTypeFrom(Method method) {
|
||||
|
||||
TypeInformation<?> returnType = ClassTypeInformation.fromReturnTypeOf(method);
|
||||
return QueryExecutionConverters.supports(returnType.getType()) ? returnType.getRequiredComponentType() : returnType;
|
||||
return QueryExecutionConverters.supports(returnType.getType())
|
||||
|| ReactiveWrapperConverters.supports(returnType.getType()) ? returnType.getRequiredComponentType()
|
||||
: returnType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.concurrent.Future;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -45,6 +46,7 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Maciek Opała
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class QueryMethodUnitTests {
|
||||
|
||||
@@ -208,7 +210,7 @@ class QueryMethodUnitTests {
|
||||
* @see DATACMNS-940
|
||||
*/
|
||||
@Test
|
||||
void detectsSinglValueWrapperWithinWrapper() throws Exception {
|
||||
void detectsSingleValueWrapperWithinWrapper() throws Exception {
|
||||
|
||||
RepositoryMetadata repositoryMetadata = new DefaultRepositoryMetadata(SampleRepository.class);
|
||||
Method method = SampleRepository.class.getMethod("returnsFutureOfOption");
|
||||
@@ -234,6 +236,19 @@ class QueryMethodUnitTests {
|
||||
assertThat(new QueryMethod(method, metadata, factory).isCollectionQuery()).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1762
|
||||
void detectsReactiveSliceQuery() throws Exception {
|
||||
|
||||
RepositoryMetadata repositoryMetadata = new DefaultRepositoryMetadata(SampleRepository.class);
|
||||
Method method = SampleRepository.class.getMethod("reactiveSlice");
|
||||
|
||||
QueryMethod queryMethod = new QueryMethod(method, repositoryMetadata, factory);
|
||||
ReturnedType returnedType = queryMethod.getResultProcessor().getReturnedType();
|
||||
assertThat(queryMethod.isSliceQuery()).isTrue();
|
||||
assertThat(returnedType.getTypeToRead()).isEqualTo(User.class);
|
||||
assertThat(returnedType.getDomainType()).isEqualTo(User.class);
|
||||
}
|
||||
|
||||
interface SampleRepository extends Repository<User, Serializable> {
|
||||
|
||||
String pagingMethodWithInvalidReturnType(Pageable pageable);
|
||||
@@ -278,6 +293,8 @@ class QueryMethodUnitTests {
|
||||
Future<Seq<User>> returnsFutureOfSeq();
|
||||
|
||||
Future<Option<User>> returnsFutureOfOption();
|
||||
|
||||
Mono<Slice<User>> reactiveSlice();
|
||||
}
|
||||
|
||||
class User {
|
||||
|
||||
Reference in New Issue
Block a user