From ce076cd99f974cd62825678cc9ce31ec7293aab9 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 1 Aug 2018 13:53:00 +0200 Subject: [PATCH] DATACMNS-1174 - Reject reactive repository implementation by default. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now reject reactive repository metadata by RepositoryConfigurationExtensionSupport.useRepositoryConfiguration(…) assuming that Spring Data modules provide only imperative repository support by default. Reactive store modules are required to override useRepositoryConfiguration(…) anyway to not accidentally implement imperative repositories with a reactive Repository extension. --- ...positoryConfigurationExtensionSupport.java | 14 +++++++- ...onfigurationExtensionSupportUnitTests.java | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java index 6fb0007c0..77d496fa0 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupport.java @@ -33,6 +33,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.io.ResourceLoader; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.AbstractRepositoryMetadata; import org.springframework.util.Assert; @@ -300,12 +301,23 @@ public abstract class RepositoryConfigurationExtensionSupport implements Reposit } /** - * Return whether to use the configuration for the repository with the given metadata. Defaults to {@literal true}. + * Return whether to use the configuration for the repository with the given metadata. Defaults to {@literal true} and + * {@link InvalidDataAccessApiUsageException} for {@link RepositoryMetadata#isReactiveRepository() reactive + * repositories}. Must be overridden by store modules that wish to provide reactive repositories. * * @param metadata will never be {@literal null}. + * @throws InvalidDataAccessApiUsageException on {@link RepositoryMetadata#isReactiveRepository() repositories} by + * default. * @return */ protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) { + + if (metadata.isReactiveRepository()) { + throw new InvalidDataAccessApiUsageException( + String.format("Reactive Repositories are not supported by %s. Offending repository is %s!", getModuleName(), + metadata.getRepositoryInterface().getName())); + } + return true; } diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupportUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupportUnitTests.java index 32f3deea3..f7f0e7254 100755 --- a/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupportUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationExtensionSupportUnitTests.java @@ -16,17 +16,29 @@ package org.springframework.data.repository.config; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; import java.lang.annotation.Annotation; import java.util.Collection; import java.util.Collections; import org.junit.Test; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.StandardAnnotationMetadata; +import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.core.support.AbstractRepositoryMetadata; import org.springframework.data.repository.core.support.RepositoryFactorySupport; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; /** * Unit tests for {@link RepositoryConfigurationExtensionSupport}. @@ -58,6 +70,22 @@ public class RepositoryConfigurationExtensionSupportUnitTests { assertThat(extension.isStrictRepositoryCandidate(metadata)).isTrue(); } + @Test // DATACMNS-1174 + public void rejectsReactiveRepositories() { + + AnnotationMetadata annotationMetadata = new StandardAnnotationMetadata(ReactiveConfiguration.class, true); + Environment environment = new StandardEnvironment(); + ResourceLoader resourceLoader = new DefaultResourceLoader(); + BeanDefinitionRegistry registry = mock(BeanDefinitionRegistry.class); + + RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(annotationMetadata, + EnableRepositories.class, resourceLoader, environment, registry); + + assertThatThrownBy(() -> extension.getRepositoryConfigurations(source, resourceLoader)) + .isInstanceOf(InvalidDataAccessApiUsageException.class) + .hasMessageContaining("Reactive Repositories are not supported"); + } + static class SampleRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport { @Override @@ -90,10 +118,16 @@ public class RepositoryConfigurationExtensionSupportUnitTests { interface PlainTypeRepository extends Repository {} + interface ReactiveRepository extends ReactiveCrudRepository {} + interface StoreInterface {} interface ExtendingInterface extends StoreInterface, Repository {} @EnableRepositories static class SampleConfiguration {} + + @EnableRepositories(includeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = ReactiveRepository.class) }, + basePackageClasses = ReactiveRepository.class, considerNestedRepositories = true) + class ReactiveConfiguration {} }