DATACMNS-526 - Improved configuration behavior in multi-store scenarios.
We now apply a stricter repository interface selection if we detect multiple Spring Data modules to be in the classpath to avoid the repository scanning accidentally overriding each others definitions or even picking up interfaces they weren't intended to manage. The detection is based on a type scan in dedicated base package where subtypes of RepositoryFactorySupport usually reside. If more than one type is found, we activate strict scanning. The strict check is actually implemented in RepositoryConfigurationExtensionSupport to be accessible for store implementations. By default we try to load the repository candidate interface and inspect the managed domain types for a collection of annotations (see RepositoryConfigurationExtensionSupport.getIdentifyingAnnotations()). Implementors still have the chance to customize the behavior by overriding isStrictRepositoryCandidate(…). We also introduced a getModuleName() to be able to create better logging output in terms of repository registration. Moved registration of RepositoryConfigurationExtension as Spring bean into the base types for XML and annotation configuration support to make sure they only kick in if explicit configuration is used.
This commit is contained in:
@@ -23,6 +23,8 @@ import java.util.Collection;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
@@ -127,16 +129,26 @@ public class AnnotationRepositoryConfigurationSourceUnitTests {
|
||||
public void returnsEmptyStringForBasePackage() throws Exception {
|
||||
|
||||
StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(getClass().getClassLoader().loadClass(
|
||||
"TypeInDefaultPackage"));
|
||||
"TypeInDefaultPackage"), true);
|
||||
RepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata,
|
||||
EnableRepositories.class, resourceLoader, environment);
|
||||
|
||||
assertThat(configurationSource.getBasePackages(), hasItem(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-526
|
||||
*/
|
||||
@Test
|
||||
public void detectsExplicitFilterConfiguration() {
|
||||
|
||||
assertThat(getConfigSource(ConfigurationWithExplicitFilter.class).usesExplicitFilters(), is(true));
|
||||
assertThat(getConfigSource(DefaultConfiguration.class).usesExplicitFilters(), is(false));
|
||||
}
|
||||
|
||||
private AnnotationRepositoryConfigurationSource getConfigSource(Class<?> type) {
|
||||
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(type);
|
||||
AnnotationMetadata metadata = new StandardAnnotationMetadata(type, true);
|
||||
return new AnnotationRepositoryConfigurationSource(metadata, EnableRepositories.class, resourceLoader, environment);
|
||||
}
|
||||
|
||||
@@ -150,4 +162,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests {
|
||||
|
||||
@EnableRepositories(considerNestedRepositories = true)
|
||||
static class DefaultConfigurationWithNestedRepositories {}
|
||||
|
||||
@EnableRepositories(excludeFilters = { @Filter(Primary.class) })
|
||||
static class ConfigurationWithExplicitFilter {}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2013 the original author or authors.
|
||||
* Copyright 2012-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -74,7 +74,7 @@ public class RepositoryComponentProviderUnitTests {
|
||||
Set<BeanDefinition> components = provider.findCandidateComponents("org.springframework.data.repository.config");
|
||||
String nestedRepositoryClassName = "org.springframework.data.repository.config.RepositoryComponentProviderUnitTests$MyNestedRepository";
|
||||
|
||||
assertThat(components.size(), is(3));
|
||||
assertThat(components.size(), is(greaterThanOrEqualTo(1)));
|
||||
assertThat(components,
|
||||
Matchers.<BeanDefinition> hasItem(hasProperty("beanClassName", is(nestedRepositoryClassName))));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.repository.config;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link RepositoryConfigurationExtensionSupport}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class RepositoryConfigurationExtensionSupportUnitTests {
|
||||
|
||||
RepositoryConfigurationExtensionSupport extension = new SampleRepositoryConfigurationExtension();
|
||||
|
||||
/**
|
||||
* @see DATACMNS-526
|
||||
*/
|
||||
@Test
|
||||
public void doesNotConsiderRepositoryForPlainTypeStrictMatch() {
|
||||
assertThat(extension.isStrictRepositoryCandidate(PlainTypeRepository.class), is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACMNS-526
|
||||
*/
|
||||
@Test
|
||||
public void considersRepositoryWithAnnotatedTypeStrictMatch() {
|
||||
assertThat(extension.isStrictRepositoryCandidate(AnnotatedTypeRepository.class), is(true));
|
||||
}
|
||||
|
||||
static class SampleRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getModulePrefix()
|
||||
*/
|
||||
@Override
|
||||
protected String getModulePrefix() {
|
||||
return "core";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryFactoryClassName()
|
||||
*/
|
||||
@Override
|
||||
public String getRepositoryFactoryClassName() {
|
||||
return RepositoryFactorySupport.class.getName();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getIdentifyingAnnotations()
|
||||
*/
|
||||
@Override
|
||||
protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
|
||||
return Collections.<Class<? extends Annotation>> singleton(Primary.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Primary
|
||||
static class AnnotatedType {}
|
||||
|
||||
static class PlainType {}
|
||||
|
||||
interface AnnotatedTypeRepository extends Repository<AnnotatedType, Long> {}
|
||||
|
||||
interface PlainTypeRepository extends Repository<PlainType, Long> {}
|
||||
}
|
||||
Reference in New Issue
Block a user