diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java index 31d6db150..6008944dd 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/DefaultRepositoryInformation.java @@ -16,6 +16,7 @@ package org.springframework.data.repository.core.support; import static org.springframework.data.repository.util.ClassUtils.*; +import static org.springframework.core.GenericTypeResolver.*; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -25,6 +26,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.springframework.core.GenericTypeResolver; +import org.springframework.core.MethodParameter; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; @@ -248,23 +251,20 @@ class DefaultRepositoryInformation implements RepositoryInformation { Type[] genericTypes = baseClassMethod.getGenericParameterTypes(); Class[] types = baseClassMethod.getParameterTypes(); - Class[] methodParameters = method.getParameterTypes(); for (int i = 0; i < genericTypes.length; i++) { Type type = genericTypes[i]; + MethodParameter parameter = new MethodParameter(method, i); + Class parameterType = resolveParameterType(parameter, metadata.getRepositoryInterface()); if (type instanceof TypeVariable) { - String name = ((TypeVariable) type).getName(); - - if (!matchesGenericType(name, methodParameters[i])) { + if (!matchesGenericType(name, parameterType)) { return false; } - } else { - - if (!types[i].equals(methodParameters[i])) { + if (!types[i].equals(parameterType)) { return false; } } diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java index db6bcaa14..a8e07c644 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/querydsl/SimpleEntityPathResolverUnitTests.java @@ -18,9 +18,10 @@ package org.springframework.data.querydsl; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; -import com.mysema.query.annotations.QueryEntity; import org.junit.Test; +import com.mysema.query.annotations.QueryEntity; + /** * Unit test for {@link SimpleEntityPathResolver}. @@ -35,15 +36,15 @@ public class SimpleEntityPathResolverUnitTests { @Test public void createsRepositoryFromDomainClassCorrectly() throws Exception { - assertThat(resolver.createPath(User.class), is(QUser.class)); + assertThat((QUser) resolver.createPath(User.class), isA(QUser.class)); } @Test public void resolvesEntityPathForInnerClassCorrectly() throws Exception { - assertThat(resolver.createPath(NamedUser.class), - is(QSimpleEntityPathResolverUnitTests_NamedUser.class)); + assertThat((QSimpleEntityPathResolverUnitTests_NamedUser) resolver.createPath(NamedUser.class), + isA(QSimpleEntityPathResolverUnitTests_NamedUser.class)); } diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryInformationUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryInformationUnitTests.java index ed689acc2..283b42b4f 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryInformationUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/DefaultRepositoryInformationUnitTests.java @@ -5,17 +5,23 @@ import static org.junit.Assert.*; import java.io.Serializable; import java.lang.reflect.Method; +import java.util.List; +import org.hamcrest.Matcher; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.core.support.DefaultRepositoryInformation; -import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; import org.springframework.data.repository.core.support.DefaultRepositoryMetadataUnitTests.DummyGenericRepositorySupport; +import org.springframework.data.repository.core.support.RepositoryFactorySupportUnitTests.ReadOnlyRepository; /** * @author Oliver Gierke @@ -25,7 +31,7 @@ public class DefaultRepositoryInformationUnitTests { @SuppressWarnings("rawtypes") static final Class REPOSITORY = DummyGenericRepositorySupport.class; - + @Mock FooRepositoryCustom customImplementation; @@ -51,28 +57,55 @@ public class DefaultRepositoryInformationUnitTests { assertThat(information.getTargetClassMethod(method), is(method)); } - + @Test public void discoversCustomlyImplementedCrudMethod() throws SecurityException, NoSuchMethodException { RepositoryMetadata metadata = new DefaultRepositoryMetadata(FooRepository.class); - RepositoryInformation information = new DefaultRepositoryInformation(metadata, CrudRepository.class, customImplementation.getClass()); - + RepositoryInformation information = new DefaultRepositoryInformation(metadata, CrudRepository.class, + customImplementation.getClass()); + Method source = FooRepositoryCustom.class.getMethod("save", User.class); Method expected = customImplementation.getClass().getMethod("save", User.class); - + assertThat(information.getTargetClassMethod(source), is(expected)); } - + @Test public void considersIntermediateMethodsAsFinderMethods() { - + RepositoryMetadata metadata = new DefaultRepositoryMetadata(ConcreteRepository.class); RepositoryInformation information = new DefaultRepositoryInformation(metadata, CrudRepository.class, null); - + assertThat(information.hasCustomMethod(), is(false)); } + @Test + public void discoversIntermediateMethodsAsBackingMethods() throws NoSuchMethodException, SecurityException { + + DefaultRepositoryMetadata metadata = new DefaultRepositoryMetadata(CustomRepository.class); + DefaultRepositoryInformation information = new DefaultRepositoryInformation(metadata, + PagingAndSortingRepository.class, null); + + Method method = CustomRepository.class.getMethod("findAll", Pageable.class); + assertThat(information.isBaseClassMethod(method), is(true)); + + method = getMethodFrom(CustomRepository.class, "exists"); + assertThat(information.isBaseClassMethod(method), is(true)); + + Matcher> empty = iterableWithSize(0); + assertThat(information.getQueryMethods(), is(empty)); + } + + private Method getMethodFrom(Class type, String name) { + for (Method method : type.getMethods()) { + if (method.getName().equals(name)) { + return method; + } + } + return null; + } + interface FooRepository extends CrudRepository, FooRepositoryCustom { // Redeclared method @@ -81,9 +114,9 @@ public class DefaultRepositoryInformationUnitTests { // Not a redeclared method User findOne(Long primaryKey); } - + interface FooRepositoryCustom { - + User save(User user); } @@ -98,14 +131,32 @@ public class DefaultRepositoryInformationUnitTests { } } - interface BaseRepository extends CrudRepository { - + T findBySomething(String something); } - + interface ConcreteRepository extends BaseRepository { - + User findBySomethingDifferent(String somethingDifferent); } + + interface ReadOnlyRepository extends Repository { + + T findOne(ID id); + + Iterable findAll(); + + Page findAll(Pageable pageable); + + List findAll(Sort sort); + + boolean exists(ID id); + + long count(); + } + + interface CustomRepository extends ReadOnlyRepository { + + } } diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java index 27c72ea0f..de1b7e9db 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java @@ -20,12 +20,17 @@ import static org.mockito.Mockito.*; import java.io.Serializable; import java.lang.reflect.Method; +import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.springframework.data.repository.CrudRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.EntityInformation; import org.springframework.data.repository.core.NamedQueries; @@ -46,7 +51,7 @@ public class RepositoryFactorySupportUnitTests { RepositoryFactorySupport factory = new DummyRepositoryFactory(); @Mock - CrudRepository backingRepo; + PagingAndSortingRepository backingRepo; @Mock ObjectRepositoryCustom customImplementation; @@ -87,6 +92,16 @@ public class RepositoryFactorySupportUnitTests { verify(customImplementation, times(1)).findOne(1); verify(backingRepo, times(0)).findOne(1); } + + @Test + public void createsRepositoryInstanceWithCustomIntermediateRepository() { + + CustomRepository repository = factory.getRepository(CustomRepository.class); + Pageable pageable = new PageRequest(0, 10); + repository.findAll(pageable); + + verify(backingRepo, times(1)).findAll(pageable); + } class DummyRepositoryFactory extends RepositoryFactorySupport { @@ -112,7 +127,7 @@ public class RepositoryFactorySupportUnitTests { @Override protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { - return CrudRepository.class; + return backingRepo.getClass(); } @@ -157,4 +172,23 @@ public class RepositoryFactorySupportUnitTests { interface MyRepositoryQuery extends RepositoryQuery { } + + interface ReadOnlyRepository extends Repository { + + T findOne(ID id); + + Iterable findAll(); + + Page findAll(Pageable pageable); + + List findAll(Sort sort); + + boolean exists(ID id); + + long count(); + } + + interface CustomRepository extends ReadOnlyRepository { + + } }