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 23715d0c0..dee86ba63 100644 --- a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java @@ -48,6 +48,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura private static final String NAMED_QUERIES_LOCATION = "namedQueriesLocation"; private static final String QUERY_LOOKUP_STRATEGY = "queryLookupStrategy"; private static final String REPOSITORY_FACTORY_BEAN_CLASS = "repositoryFactoryBeanClass"; + private static final String CONSIDER_NESTED_REPOSITORIES = "considerNestedRepositories"; private final AnnotationMetadata metadata; private final AnnotationAttributes attributes; @@ -222,4 +223,12 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura } return typeFilters; } + + /* (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationSourceSupport#isConsideringNestedRepositoriesEnabled() + */ + @Override + public boolean isConsideringNestedRepositoriesEnabled() { + return attributes.getBoolean(CONSIDER_NESTED_REPOSITORIES); + } } diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java b/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java index 3ac9d72c3..632311312 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java @@ -1,3 +1,18 @@ +/* + * 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. + * 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 java.io.IOException; @@ -26,6 +41,8 @@ import org.springframework.util.Assert; */ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentProvider { + private boolean considerNestedRepositoryInterfaces; + /** * Creates a new {@link RepositoryComponentProvider} using the given {@link TypeFilter} to include components to be * picked up. @@ -83,8 +100,26 @@ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentPro boolean isNonRepositoryInterface = !ClassUtils.isGenericRepositoryInterface(beanDefinition.getBeanClassName()); boolean isTopLevelType = !beanDefinition.getMetadata().hasEnclosingClass(); + boolean isConsiderNestedRepositories = isConsiderNestedRepositoryInterfaces(); - return isNonRepositoryInterface && isTopLevelType; + return isNonRepositoryInterface && (isTopLevelType || isConsiderNestedRepositories); + } + + /** + * @return the considerNestedRepositoryInterfaces + */ + public boolean isConsiderNestedRepositoryInterfaces() { + return considerNestedRepositoryInterfaces; + } + + /** + * Controls whether nested inner-class {@link Repository} interface definitions should be considered for automatic + * discovery. This defaults to {@literal false}. + * + * @param considerNestedRepositoryInterfaces + */ + public void setConsiderNestedRepositoryInterfaces(boolean considerNestedRepositoryInterfaces) { + this.considerNestedRepositoryInterfaces = considerNestedRepositoryInterfaces; } /** diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java index 8446e8120..67fad5450 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.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. @@ -25,6 +25,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy; * Interface containing the configurable options for the Spring Data repository subsystem. * * @author Oliver Gierke + * @author Thomas Darimont */ public interface RepositoryConfigurationSource { @@ -76,4 +77,9 @@ public interface RepositoryConfigurationSource { * @return */ Collection getCandidates(ResourceLoader loader); + + /** + * @return true if the container should look for nested repository interface definitions. + */ + boolean isConsideringNestedRepositoriesEnabled(); } 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 088ffbe4a..d0768aa7f 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -21,7 +21,6 @@ import java.util.HashSet; 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; @@ -54,7 +53,8 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository */ public Collection getCandidates(ResourceLoader loader) { - ClassPathScanningCandidateComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters()); + RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters()); + scanner.setConsiderNestedRepositoryInterfaces(isConsideringNestedRepositoriesEnabled()); scanner.setResourceLoader(loader); scanner.setEnvironment(environment); @@ -93,4 +93,10 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository protected Iterable getIncludeFilters() { return Collections.emptySet(); } + + /** + * Controls whether nested repository-interfaces (e.g. defined as inner classes) should be considered by the + * repository infrastructure. + */ + public abstract boolean isConsideringNestedRepositoriesEnabled(); } 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 96860189e..7c9bc9224 100644 --- a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.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. @@ -31,6 +31,7 @@ import org.w3c.dom.Element; * XML based {@link RepositoryConfigurationSource}. Uses configuration defined on {@link Element} attributes. * * @author Oliver Gierke + * @author Thomas Darimont */ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSourceSupport { @@ -39,6 +40,7 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou private static final String NAMED_QUERIES_LOCATION = "named-queries-location"; private static final String REPOSITORY_IMPL_POSTFIX = "repository-impl-postfix"; private static final String REPOSITORY_FACTORY_BEAN_CLASS_NAME = "factory-class"; + private static final String CONSIDER_NESTED_REPOSITORIES = "consider-nested-repositories"; private final Element element; private final ParserContext context; @@ -148,4 +150,14 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou String attribute = element.getAttribute(attributeName); return StringUtils.hasText(attribute) ? attribute : null; } + + /* (non-Javadoc) + * @see org.springframework.data.repository.config.RepositoryConfigurationSourceSupport#isConsideringNestedRepositoriesEnabled() + */ + @Override + public boolean isConsideringNestedRepositoriesEnabled() { + + String attribute = getNullDefaultedAttribute(element, CONSIDER_NESTED_REPOSITORIES); + return attribute != null && Boolean.parseBoolean(attribute); + } } diff --git a/src/main/resources/META-INF/spring.schemas b/src/main/resources/META-INF/spring.schemas index c67a885cb..620dd602d 100644 --- a/src/main/resources/META-INF/spring.schemas +++ b/src/main/resources/META-INF/spring.schemas @@ -2,4 +2,5 @@ http\://www.springframework.org/schema/data/repository/spring-repository-1.0.xsd http\://www.springframework.org/schema/data/repository/spring-repository-1.4.xsd=org/springframework/data/repository/config/spring-repository-1.4.xsd http\://www.springframework.org/schema/data/repository/spring-repository-1.5.xsd=org/springframework/data/repository/config/spring-repository-1.5.xsd http\://www.springframework.org/schema/data/repository/spring-repository-1.6.xsd=org/springframework/data/repository/config/spring-repository-1.6.xsd -http\://www.springframework.org/schema/data/repository/spring-repository.xsd=org/springframework/data/repository/config/spring-repository-1.6.xsd +http\://www.springframework.org/schema/data/repository/spring-repository-1.7.xsd=org/springframework/data/repository/config/spring-repository-1.7.xsd +http\://www.springframework.org/schema/data/repository/spring-repository.xsd=org/springframework/data/repository/config/spring-repository-1.7.xsd diff --git a/src/main/resources/org/springframework/data/repository/config/spring-repository-1.7.xsd b/src/main/resources/org/springframework/data/repository/config/spring-repository-1.7.xsd new file mode 100644 index 000000000..cd642a68d --- /dev/null +++ b/src/main/resources/org/springframework/data/repository/config/spring-repository-1.7.xsd @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Where to find the files to read the objects from the repository shall be populated with. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file 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 e217f3218..5e6681b4e 100644 --- a/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java @@ -32,6 +32,7 @@ import org.springframework.core.type.StandardAnnotationMetadata; * Unit tests for {@link AnnotationRepositoryConfigurationSource}. * * @author Oliver Gierke + * @author Thomas Darimont */ public class AnnotationRepositoryConfigurationSourceUnitTests { @@ -70,6 +71,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { Iterable packages = source.getBasePackages(); assertThat(packages, hasItem(DefaultConfiguration.class.getPackage().getName())); + assertThat(source.isConsideringNestedRepositoriesEnabled(), is(false)); } @Test @@ -83,17 +85,27 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { assertThat(packages, hasItem("foo")); } - public static class Person { + /** + * @see DATACMNS-90 + */ + @Test + public void returnsConsiderNestedRepositories() { + AnnotationMetadata metadata = new StandardAnnotationMetadata(DefaultConfigurationWithNestedRepositories.class); + RepositoryConfigurationSource source = new AnnotationRepositoryConfigurationSource(metadata, + EnableRepositories.class, environment); + + assertThat(source.isConsideringNestedRepositoriesEnabled(), is(true)); } + public static class Person {} + @EnableRepositories - static class DefaultConfiguration { - - } + static class DefaultConfiguration {} @EnableRepositories(basePackages = "foo") - static class DefaultConfigurationWithBasePackage { + static class DefaultConfigurationWithBasePackage {} - } + @EnableRepositories(considerNestedRepositories = true) + static class DefaultConfigurationWithNestedRepositories {} } diff --git a/src/test/java/org/springframework/data/repository/config/EnableRepositories.java b/src/test/java/org/springframework/data/repository/config/EnableRepositories.java index 431694aee..88214f621 100644 --- a/src/test/java/org/springframework/data/repository/config/EnableRepositories.java +++ b/src/test/java/org/springframework/data/repository/config/EnableRepositories.java @@ -44,4 +44,6 @@ public @interface EnableRepositories { String namedQueriesLocation() default ""; String repositoryImplementationPostfix() default "Impl"; + + boolean considerNestedRepositories() default false; } diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java index 70be2565c..234a4a881 100644 --- a/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.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. @@ -23,16 +23,20 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import org.hamcrest.Matchers; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; +import org.springframework.data.repository.Repository; +import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSourceUnitTests.Person; import org.springframework.data.repository.sample.SampleAnnotatedRepository; /** * Unit tests for {@link RepositoryComponentProvider}. * * @author Oliver Gierke + * @author Thomas Darimont */ public class RepositoryComponentProviderUnitTests { @@ -57,4 +61,23 @@ public class RepositoryComponentProviderUnitTests { assertThat(components.size(), is(1)); assertThat(components.iterator().next().getBeanClassName(), is(MyOtherRepository.class.getName())); } + + /** + * @DATACMNS-90 + */ + @Test + public void shouldConsiderNestedRepositoryInterfacesIfEnabled() { + + RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections. emptyList()); + provider.setConsiderNestedRepositoryInterfaces(true); + + Set components = provider.findCandidateComponents("org.springframework.data.repository.config"); + String nestedRepositoryClassName = "org.springframework.data.repository.config.RepositoryComponentProviderUnitTests$MyNestedRepository"; + + assertThat(components.size(), is(3)); + assertThat(components, + Matchers. hasItem(hasProperty("beanClassName", is(nestedRepositoryClassName)))); + } + + public interface MyNestedRepository extends Repository {} } diff --git a/src/test/java/org/springframework/data/repository/config/ResourceReaderRepositoryPopulatorBeanDefinitionParserIntegrationTests.java b/src/test/java/org/springframework/data/repository/config/ResourceReaderRepositoryPopulatorBeanDefinitionParserIntegrationTests.java index 2f678a021..40c459a1b 100644 --- a/src/test/java/org/springframework/data/repository/config/ResourceReaderRepositoryPopulatorBeanDefinitionParserIntegrationTests.java +++ b/src/test/java/org/springframework/data/repository/config/ResourceReaderRepositoryPopulatorBeanDefinitionParserIntegrationTests.java @@ -33,7 +33,7 @@ import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.test.util.ReflectionTestUtils; /** - * Integratin tests for the initializer namespace elements. + * Integration tests for the initializer name-space elements. * * @author Oliver Gierke */