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.
This commit is contained in:
Oliver Gierke
2018-04-16 16:25:55 +02:00
parent 48a7a023f8
commit 0daac0c890
3 changed files with 38 additions and 1 deletions

View File

@@ -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);

View File

@@ -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, Long> {
User findSingle();
@@ -148,4 +158,13 @@ public class AbstractRepositoryMetadataUnitTests {
}
}
// DATACMNS-1299
class Element {}
abstract class Container implements Iterable<Element> {}
interface ContainerRepository extends Repository<Container, Long> {
Container someMethod();
}
}

View File

@@ -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<Object> returnType = ClassTypeInformation.fromReturnTypeOf(method);
assertThat(QueryExecutionConverters.unwrapWrapperTypes(returnType), //
is((TypeInformation) ClassTypeInformation.from(String.class)));
}
interface Sample {
Page<String> pages();
}
// Vavr
@SuppressWarnings("unchecked")