From d10560f2388e5f4263efa23e9fadc73ffab9ed24 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 25 Sep 2020 16:25:35 +0200 Subject: [PATCH] =?UTF-8?q?DATACMNS-1762=20-=20Reintroduce=20calls=20to=20?= =?UTF-8?q?ReactiveWrapperConverters.supports(=E2=80=A6)=20after=20decoupl?= =?UTF-8?q?ing=20from=20QueryExecutionConverters.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../support/AbstractRepositoryMetadata.java | 6 +----- .../support/QueryExecutionResultHandler.java | 3 ++- .../data/repository/query/Parameter.java | 2 +- .../query/ParametersParameterAccessor.java | 4 +++- .../data/repository/query/QueryMethod.java | 4 +++- .../data/repository/util/ClassUtils.java | 4 +++- .../query/QueryMethodUnitTests.java | 19 ++++++++++++++++++- 7 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java b/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java index e79af5b61..72011696f 100644 --- a/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java +++ b/src/main/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadata.java @@ -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(); } diff --git a/src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java b/src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java index 1424c7a2d..b1a14f9c8 100644 --- a/src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java +++ b/src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java @@ -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); diff --git a/src/main/java/org/springframework/data/repository/query/Parameter.java b/src/main/java/org/springframework/data/repository/query/Parameter.java index faca4ba02..46035e77c 100644 --- a/src/main/java/org/springframework/data/repository/query/Parameter.java +++ b/src/main/java/org/springframework/data/repository/query/Parameter.java @@ -230,7 +230,7 @@ public class Parameter { TypeInformation returnType = ClassTypeInformation.fromReturnTypeOf(method); return bound - .equals(ReactiveWrapperConverters.unwrapWrapperTypes(QueryExecutionConverters.unwrapWrapperTypes(returnType))); + .equals(QueryExecutionConverters.unwrapWrapperTypes(ReactiveWrapperConverters.unwrapWrapperTypes(returnType))); } /** diff --git a/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java b/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java index 3582d01a9..fcf6aae3b 100644 --- a/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java +++ b/src/main/java/org/springframework/data/repository/query/ParametersParameterAccessor.java @@ -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; } } diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/src/main/java/org/springframework/data/repository/query/QueryMethod.java index 7d851913a..ed4394726 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -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 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> correctly. diff --git a/src/main/java/org/springframework/data/repository/util/ClassUtils.java b/src/main/java/org/springframework/data/repository/util/ClassUtils.java index f10bd1f0a..4ef5045bf 100644 --- a/src/main/java/org/springframework/data/repository/util/ClassUtils.java +++ b/src/main/java/org/springframework/data/repository/util/ClassUtils.java @@ -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; } } diff --git a/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java b/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java index 94d1d78b2..62779269c 100755 --- a/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java @@ -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 { String pagingMethodWithInvalidReturnType(Pageable pageable); @@ -278,6 +293,8 @@ class QueryMethodUnitTests { Future> returnsFutureOfSeq(); Future> returnsFutureOfOption(); + + Mono> reactiveSlice(); } class User {