From 29a6688e8cea083a0e4a09c625669da1c04ce538 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 28 Jul 2016 13:08:43 +0200 Subject: [PATCH] DATAMONGO-1470 - AbstractMongoConfiguration now supports multiple base packages for @Document scanning. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced AbstractMongoConfiguration.getMappingBasePackages() to return multiple ones over the previously existing ….getMappingBasePackage(). The former is now used by the code triggering the scanning using what the latter returns by default. --- .../config/AbstractMongoConfiguration.java | 57 ++++++++++++++++--- .../src/test/java/example/first/First.java | 26 +++++++++ .../src/test/java/example/second/Second.java | 26 +++++++++ .../AbstractMongoConfigurationUnitTests.java | 51 +++++++++++++++-- 4 files changed, 147 insertions(+), 13 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/example/first/First.java create mode 100644 spring-data-mongodb/src/test/java/example/second/Second.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java index b3915c753..e1e92eee5 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/AbstractMongoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2015 the original author or authors. + * Copyright 2011-2016 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. @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.config; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -118,17 +119,33 @@ public abstract class AbstractMongoConfiguration { * Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration * class' (the concrete class, not this one here) by default. So if you have a {@code com.acme.AppConfig} extending * {@link AbstractMongoConfiguration} the base package will be considered {@code com.acme} unless the method is - * overriden to implement alternate behaviour. + * overridden to implement alternate behavior. * * @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for * entities. + * @deprecated use {@link #getMappingBasePackages()} instead. */ + @Deprecated protected String getMappingBasePackage() { Package mappingBasePackage = getClass().getPackage(); return mappingBasePackage == null ? null : mappingBasePackage.getName(); } + /** + * Returns the base packages to scan for MongoDB mapped entities at startup. Will return the package name of the + * configuration class' (the concrete class, not this one here) by default. So if you have a + * {@code com.acme.AppConfig} extending {@link AbstractMongoConfiguration} the base package will be considered + * {@code com.acme} unless the method is overridden to implement alternate behavior. + * + * @return the base packages to scan for mapped {@link Document} classes or an empty collection to not enable scanning + * for entities. + * @since 1.10 + */ + protected Collection getMappingBasePackages() { + return Collections.singleton(getMappingBasePackage()); + } + /** * Return {@link UserCredentials} to be used when connecting to the MongoDB instance or {@literal null} if none shall * be used. @@ -204,26 +221,52 @@ public abstract class AbstractMongoConfiguration { } /** - * Scans the mapping base package for classes annotated with {@link Document}. + * Scans the mapping base package for classes annotated with {@link Document}. By default, it scans for entities in + * all packages returned by {@link #getMappingBasePackages()}. * - * @see #getMappingBasePackage() + * @see #getMappingBasePackages() * @return * @throws ClassNotFoundException */ protected Set> getInitialEntitySet() throws ClassNotFoundException { - String basePackage = getMappingBasePackage(); + Set> initialEntitySet = new HashSet>(); + + for (String basePackage : getMappingBasePackages()) { + initialEntitySet.addAll(scanForEntities(basePackage)); + } + + return initialEntitySet; + } + + /** + * Scans the given base package for entities, i.e. MongoDB specific types annotated with {@link Document} and + * {@link Persistent}. + * + * @param basePackage must not be {@literal null}. + * @return + * @throws ClassNotFoundException + * @since 1.10 + */ + protected Set> scanForEntities(String basePackage) throws ClassNotFoundException { + + if (!StringUtils.hasText(basePackage)) { + return Collections.emptySet(); + } + Set> initialEntitySet = new HashSet>(); if (StringUtils.hasText(basePackage)) { + ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider( false); componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class)); componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class)); for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) { - initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), - AbstractMongoConfiguration.class.getClassLoader())); + + initialEntitySet + .add(ClassUtils.forName(candidate.getBeanClassName(), AbstractMongoConfiguration.class.getClassLoader())); } } diff --git a/spring-data-mongodb/src/test/java/example/first/First.java b/spring-data-mongodb/src/test/java/example/first/First.java new file mode 100644 index 000000000..98e6a9fe0 --- /dev/null +++ b/spring-data-mongodb/src/test/java/example/first/First.java @@ -0,0 +1,26 @@ +/* + * Copyright 2016 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 example.first; + +import org.springframework.data.mongodb.core.mapping.Document; + +/** + * @author Oliver Gierke + */ +@Document +public class First { + +} diff --git a/spring-data-mongodb/src/test/java/example/second/Second.java b/spring-data-mongodb/src/test/java/example/second/Second.java new file mode 100644 index 000000000..5155856e0 --- /dev/null +++ b/spring-data-mongodb/src/test/java/example/second/Second.java @@ -0,0 +1,26 @@ +/* + * Copyright 2016 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 example.second; + +import org.springframework.data.mongodb.core.mapping.Document; + +/** + * @author Oliver Gierke + */ +@Document +public class Second { + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index bf4c0d01a..2bb1bd0a0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 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. @@ -18,6 +18,13 @@ package org.springframework.data.mongodb.config; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import example.first.First; +import example.second.Second; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; + import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -144,6 +151,20 @@ public class AbstractMongoConfigurationUnitTests { assertThat(new SampleMongoConfiguration().getAuthenticationDatabaseName(), is(nullValue())); } + /** + * @see DATAMONGO-1470 + */ + @Test + @SuppressWarnings("unchecked") + public void allowsMultipleEntityBasePackages() throws ClassNotFoundException { + + ConfigurationWithMultipleBasePackages config = new ConfigurationWithMultipleBasePackages(); + Set> entities = config.getInitialEntitySet(); + + assertThat(entities, hasSize(2)); + assertThat(entities, hasItems(First.class, Second.class)); + } + private static void assertScanningDisabled(final String value) throws ClassNotFoundException { AbstractMongoConfiguration configuration = new SampleMongoConfiguration() { @@ -173,9 +194,11 @@ public class AbstractMongoConfigurationUnitTests { @Bean @Override public MappingMongoConverter mappingMongoConverter() throws Exception { - MappingMongoConverter mmc = super.mappingMongoConverter(); - mmc.setTypeMapper(typeMapper()); - return mmc; + + MappingMongoConverter converter = super.mappingMongoConverter(); + converter.setTypeMapper(typeMapper()); + + return converter; } @Bean @@ -184,8 +207,24 @@ public class AbstractMongoConfigurationUnitTests { } } - @Document - static class Entity { + static class ConfigurationWithMultipleBasePackages extends AbstractMongoConfiguration { + @Override + protected String getDatabaseName() { + return "test"; + } + + @Override + public Mongo mongo() throws Exception { + return new MongoClient(); + } + + @Override + protected Collection getMappingBasePackages() { + return Arrays.asList("example.first", "example.second"); + } } + + @Document + static class Entity {} }