From 5ccb0bc9c216588a07d3abd49c450bcf048be28d Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Sun, 25 Aug 2013 18:29:52 +0200 Subject: [PATCH] DATACMNS-360 - Scanning for repository interfaces now considers active profiles. The configuration entry points (RepositoryBeanDefinitionParser and RepositoryBeanDefinitionRegistrar) now hand the Environment they're running in forward into the infrastructure scanning for repositories. Thus it will correctly find or not find repository interfaces based on which profiles are activated or not. --- ...notationRepositoryConfigurationSource.java | 43 +++++++++++-------- .../RepositoryBeanDefinitionParser.java | 6 ++- ...ositoryBeanDefinitionRegistrarSupport.java | 20 +++++++-- .../RepositoryConfigurationSourceSupport.java | 17 +++++++- .../XmlRepositoryConfigurationSource.java | 6 ++- ...epositoryConfigurationSourceUnitTests.java | 12 ++++-- .../repository/config/ProfileRepository.java | 28 ++++++++++++ ...anDefinitionRegistrarSupportUnitTests.java | 42 ++++++++++++++++-- 8 files changed, 140 insertions(+), 34 deletions(-) create mode 100644 src/test/java/org/springframework/data/repository/config/ProfileRepository.java diff --git a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java index 6023be867..23715d0c0 100644 --- a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 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. @@ -26,6 +26,7 @@ import java.util.Set; import org.springframework.beans.BeanUtils; import org.springframework.context.annotation.FilterType; import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.env.Environment; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.filter.AnnotationTypeFilter; import org.springframework.core.type.filter.AssignableTypeFilter; @@ -57,8 +58,12 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura * * @param metadata must not be {@literal null}. * @param annotation must not be {@literal null}. + * @param environment */ - public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class annotation) { + public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class annotation, + Environment environment) { + + super(environment); Assert.notNull(metadata); Assert.notNull(annotation); @@ -196,23 +201,23 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura for (Class filterClass : filterAttributes.getClassArray("value")) { switch (filterType) { - case ANNOTATION: - Assert.isAssignable(Annotation.class, filterClass, "An error occured when processing a @ComponentScan " - + "ANNOTATION type filter: "); - @SuppressWarnings("unchecked") - Class annoClass = (Class) filterClass; - typeFilters.add(new AnnotationTypeFilter(annoClass)); - break; - case ASSIGNABLE_TYPE: - typeFilters.add(new AssignableTypeFilter(filterClass)); - break; - case CUSTOM: - Assert.isAssignable(TypeFilter.class, filterClass, "An error occured when processing a @ComponentScan " - + "CUSTOM type filter: "); - typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); - break; - default: - throw new IllegalArgumentException("unknown filter type " + filterType); + case ANNOTATION: + Assert.isAssignable(Annotation.class, filterClass, "An error occured when processing a @ComponentScan " + + "ANNOTATION type filter: "); + @SuppressWarnings("unchecked") + Class annoClass = (Class) filterClass; + typeFilters.add(new AnnotationTypeFilter(annoClass)); + break; + case ASSIGNABLE_TYPE: + typeFilters.add(new AssignableTypeFilter(filterClass)); + break; + case CUSTOM: + Assert.isAssignable(TypeFilter.class, filterClass, "An error occured when processing a @ComponentScan " + + "CUSTOM type filter: "); + typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class)); + break; + default: + throw new IllegalArgumentException("unknown filter type " + filterType); } } return typeFilters; diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java index de0b20269..c1eef8669 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2012 the original author or authors. + * Copyright 2008-2013 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. @@ -27,6 +27,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.core.env.Environment; import org.springframework.util.Assert; import org.w3c.dom.Element; @@ -62,7 +63,8 @@ public class RepositoryBeanDefinitionParser implements BeanDefinitionParser { try { - XmlRepositoryConfigurationSource configSource = new XmlRepositoryConfigurationSource(element, parser); + Environment environment = parser.getDelegate().getEnvironment(); + XmlRepositoryConfigurationSource configSource = new XmlRepositoryConfigurationSource(element, parser, environment); for (RepositoryConfiguration config : extension.getRepositoryConfigurations( configSource, parser.getReaderContext().getResourceLoader())) { diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java index 5307e18f3..fe0fddcfb 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 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. @@ -22,8 +22,10 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.env.Environment; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; @@ -36,15 +38,17 @@ import org.springframework.util.ClassUtils; * @author Oliver Gierke */ public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar, - BeanClassLoaderAware, ResourceLoaderAware { + BeanClassLoaderAware, ResourceLoaderAware, EnvironmentAware { private ResourceLoader resourceLoader; private ClassLoader beanClassLoader; + private Environment environment; /* * (non-Javadoc) * @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader) */ + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } @@ -53,10 +57,20 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import * (non-Javadoc) * @see org.springframework.context.ResourceLoaderAware#setResourceLoader(org.springframework.core.io.ResourceLoader) */ + @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } + /* + * (non-Javadoc) + * @see org.springframework.context.EnvironmentAware#setEnvironment(org.springframework.core.env.Environment) + */ + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + /* * (non-Javadoc) * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry) @@ -74,7 +88,7 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import defaultExternalResources(registry); AnnotationRepositoryConfigurationSource configuration = new AnnotationRepositoryConfigurationSource( - annotationMetadata, getAnnotation()); + annotationMetadata, getAnnotation(), environment); RepositoryConfigurationExtension extension = getExtension(); extension.registerBeansForRoot(registry, configuration); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java index 7eb0edb93..088ffbe4a 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 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. @@ -22,6 +22,8 @@ import java.util.Set; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.filter.TypeFilter; @@ -34,6 +36,18 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository protected static final String DEFAULT_REPOSITORY_IMPL_POSTFIX = "Impl"; + private final Environment environment; + + /** + * Creates a new {@link RepositoryConfigurationSourceSupport} with the given environment. Defaults to a plain + * {@link StandardEnvironment} in case the given argument is {@literal null}. + * + * @param environment nullable, defaults to a {@link StandardEnvironment}. + */ + public RepositoryConfigurationSourceSupport(Environment environment) { + this.environment = environment == null ? new StandardEnvironment() : environment; + } + /* * (non-Javadoc) * @see org.springframework.data.repository.config.RepositoryConfiguration#getCandidates(org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider) @@ -42,6 +56,7 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository ClassPathScanningCandidateComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters()); scanner.setResourceLoader(loader); + scanner.setEnvironment(environment); for (TypeFilter filter : getExcludeFilters()) { scanner.addExcludeFilter(filter); diff --git a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java index 09ec18ade..96860189e 100644 --- a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java @@ -18,6 +18,7 @@ package org.springframework.data.repository.config; import java.util.Arrays; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.core.env.Environment; import org.springframework.core.type.filter.TypeFilter; import org.springframework.data.config.TypeFilterParser; import org.springframework.data.config.TypeFilterParser.Type; @@ -50,8 +51,11 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou * * @param element must not be {@literal null}. * @param context must not be {@literal null}. + * @param environment must not be {@literal null}. */ - public XmlRepositoryConfigurationSource(Element element, ParserContext context) { + public XmlRepositoryConfigurationSource(Element element, ParserContext context, Environment environment) { + + super(environment); Assert.notNull(element); Assert.notNull(context); diff --git a/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java b/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java index e112472fa..e217f3218 100644 --- a/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 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. @@ -22,6 +22,8 @@ import java.util.Collection; import org.junit.Before; import org.junit.Test; +import org.springframework.core.env.Environment; +import org.springframework.core.env.StandardEnvironment; import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.StandardAnnotationMetadata; @@ -34,12 +36,14 @@ import org.springframework.core.type.StandardAnnotationMetadata; public class AnnotationRepositoryConfigurationSourceUnitTests { RepositoryConfigurationSource source; + Environment environment; @Before public void setUp() { AnnotationMetadata annotationMetadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); - source = new AnnotationRepositoryConfigurationSource(annotationMetadata, EnableRepositories.class); + environment = new StandardEnvironment(); + source = new AnnotationRepositoryConfigurationSource(annotationMetadata, EnableRepositories.class, environment); } @Test @@ -62,7 +66,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { AnnotationMetadata metadata = new StandardAnnotationMetadata(DefaultConfiguration.class); RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(metadata, - EnableRepositories.class); + EnableRepositories.class, environment); Iterable packages = source.getBasePackages(); assertThat(packages, hasItem(DefaultConfiguration.class.getPackage().getName())); @@ -73,7 +77,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { AnnotationMetadata metadata = new StandardAnnotationMetadata(DefaultConfigurationWithBasePackage.class); RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(metadata, - EnableRepositories.class); + EnableRepositories.class, environment); Iterable packages = source.getBasePackages(); assertThat(packages, hasItem("foo")); diff --git a/src/test/java/org/springframework/data/repository/config/ProfileRepository.java b/src/test/java/org/springframework/data/repository/config/ProfileRepository.java new file mode 100644 index 000000000..98e762ff7 --- /dev/null +++ b/src/test/java/org/springframework/data/repository/config/ProfileRepository.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013 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 org.springframework.context.annotation.Profile; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSourceUnitTests.Person; + +/** + * @author Oliver Gierke + */ +@Profile("profile") +interface ProfileRepository extends Repository { + +} diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java index 627692eea..b5aba3222 100644 --- a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 the original author or authors. + * Copyright 2012-2013 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. @@ -26,6 +26,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.core.env.StandardEnvironment; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport; @@ -38,8 +39,7 @@ import org.springframework.data.repository.core.support.RepositoryFactoryBeanSup @RunWith(MockitoJUnitRunner.class) public class RepositoryBeanDefinitionRegistrarSupportUnitTests { - @Mock - BeanDefinitionRegistry registry; + @Mock BeanDefinitionRegistry registry; @Test public void registersBeanDefinitionForFoundBean() { @@ -48,7 +48,41 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests { DummyRegistrar registrar = new DummyRegistrar(); registrar.registerBeanDefinitions(metadata, registry); - verify(registry, times(1)).registerBeanDefinition(eq("myRepository"), any(BeanDefinition.class)); + assertBeanDefinitionRegisteredFor("myRepository"); + assertNoBeanDefinitionRegisteredFor("profileRepository"); + } + + /** + * @see DATACMNS-360 + */ + @Test + public void registeredProfileRepositoriesIfProfileActivated() { + + StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); + + StandardEnvironment environment = new StandardEnvironment(); + environment.setActiveProfiles("profile"); + + DummyRegistrar registrar = new DummyRegistrar(); + registrar.setEnvironment(environment); + + registrar.registerBeanDefinitions(metadata, registry); + + assertBeanDefinitionRegisteredFor("myRepository", "profileRepository"); + } + + private void assertBeanDefinitionRegisteredFor(String... names) { + + for (String name : names) { + verify(registry, times(1)).registerBeanDefinition(eq(name), any(BeanDefinition.class)); + } + } + + private void assertNoBeanDefinitionRegisteredFor(String... names) { + + for (String name : names) { + verify(registry, times(0)).registerBeanDefinition(eq(name), any(BeanDefinition.class)); + } } static class DummyRegistrar extends RepositoryBeanDefinitionRegistrarSupport {