From 0daac0c8904e0125ab5420ff0b617b4f3adbd17b Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 16 Apr 2018 16:25:55 +0200 Subject: [PATCH] DATACMNS-1299 - QueryExecutionsConverters now don't unwrap custom Iterable implementations. Instead of a simple check for assignability from Iterable, we now properly use TypeInformation.isCollectionLike(), which checks for Iterable equality or assignability of collections or arrays as well as an explicit check for Slice as that is needed to properly unwrap Page instances and Slices themselves. That prevents custom domain types implementing Iterable from being unwrapped into their element types. --- .../util/QueryExecutionConverters.java | 3 ++- .../AbstractRepositoryMetadataUnitTests.java | 19 +++++++++++++++++++ .../QueryExecutionConvertersUnitTests.java | 17 +++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java index 24d11bc5a..a5625b14b 100644 --- a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java +++ b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java @@ -253,7 +253,8 @@ public abstract class QueryExecutionConverters { Class rawType = type.getType(); - boolean needToUnwrap = Iterable.class.isAssignableFrom(rawType) // + boolean needToUnwrap = type.isCollectionLike() // + || Slice.class.isAssignableFrom(rawType) // || rawType.isArray() // || supports(rawType) // || org.springframework.data.util.ReflectionUtils.isJava8StreamType(rawType); diff --git a/src/test/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadataUnitTests.java b/src/test/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadataUnitTests.java index 10e88b627..847070475 100644 --- a/src/test/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadataUnitTests.java +++ b/src/test/java/org/springframework/data/repository/core/support/AbstractRepositoryMetadataUnitTests.java @@ -101,6 +101,16 @@ public class AbstractRepositoryMetadataUnitTests { assertThat(metadata.getReturnedDomainClass(method), is(typeCompatibleWith(User.class))); } + @Test // DATACMNS-1299 + public void doesNotUnwrapCustomTypeImplementingIterable() throws Exception { + + RepositoryMetadata metadata = AbstractRepositoryMetadata.getMetadata(ContainerRepository.class); + + Method method = ContainerRepository.class.getMethod("someMethod"); + + assertThat(metadata.getReturnedDomainClass(method), is(typeCompatibleWith(Container.class))); + } + interface UserRepository extends Repository { User findSingle(); @@ -148,4 +158,13 @@ public class AbstractRepositoryMetadataUnitTests { } } + // DATACMNS-1299 + + class Element {} + + abstract class Container implements Iterable {} + + interface ContainerRepository extends Repository { + Container someMethod(); + } } diff --git a/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java b/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java index 226c752c5..8d0cc4155 100644 --- a/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java +++ b/src/test/java/org/springframework/data/repository/util/QueryExecutionConvertersUnitTests.java @@ -40,6 +40,8 @@ import org.junit.Test; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.data.domain.Page; import org.springframework.data.domain.Slice; +import org.springframework.data.util.ClassTypeInformation; +import org.springframework.data.util.TypeInformation; import org.springframework.util.ReflectionUtils; import org.springframework.util.concurrent.ListenableFuture; @@ -341,6 +343,21 @@ public class QueryExecutionConvertersUnitTests { is(instanceOf(javaslang.collection.Set.class))); } + @Test // DATACMNS-1299 + public void unwrapsPages() throws Exception { + + Method method = Sample.class.getMethod("pages"); + TypeInformation returnType = ClassTypeInformation.fromReturnTypeOf(method); + + assertThat(QueryExecutionConverters.unwrapWrapperTypes(returnType), // + is((TypeInformation) ClassTypeInformation.from(String.class))); + } + + interface Sample { + + Page pages(); + } + // Vavr @SuppressWarnings("unchecked")