diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 643602c3b..e8e9dba85 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -113,14 +114,17 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplate.class); private static final String ID = "_id"; private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE; - @SuppressWarnings("serial") - private static final List ITERABLE_CLASSES = new ArrayList() { - { - add(List.class.getName()); - add(Collection.class.getName()); - add(Iterator.class.getName()); - } - }; + private static final Collection ITERABLE_CLASSES; + + static { + + Set iterableClasses = new HashSet(); + iterableClasses.add(List.class.getName()); + iterableClasses.add(Collection.class.getName()); + iterableClasses.add(Iterator.class.getName()); + + ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses); + } /* * WriteConcern to be used for write operations if it has been specified. @@ -247,11 +251,14 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { this.readPreference = readPreference; } + /* + * (non-Javadoc) + * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext) + */ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - String[] beans = applicationContext.getBeanNamesForType(MongoPersistentEntityIndexCreator.class); - if ((null == beans || beans.length == 0) && applicationContext instanceof ConfigurableApplicationContext) { - ((ConfigurableApplicationContext) applicationContext).addApplicationListener(indexCreator); - } + + prepareIndexCreator(applicationContext); + eventPublisher = applicationContext; if (mappingContext instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher); @@ -259,6 +266,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { resourceLoader = applicationContext; } + /** + * Inspects the given {@link ApplicationContext} for {@link MongoPersistentEntityIndexCreator} and those in turn if + * they were registered for the current {@link MappingContext}. If no creator for the current {@link MappingContext} + * can be found we manually add the internally created one as {@link ApplicationListener} to make sure indexes get + * created appropriately for entity types persisted through this {@link MongoTemplate} instance. + * + * @param context + */ + private void prepareIndexCreator(ApplicationContext context) { + + String[] indexCreators = context.getBeanNamesForType(MongoPersistentEntityIndexCreator.class); + + for (String creator : indexCreators) { + MongoPersistentEntityIndexCreator creatorBean = context.getBean(creator, MongoPersistentEntityIndexCreator.class); + if (creatorBean.isIndexCreatorFor(mappingContext)) { + return; + } + } + + if (context instanceof ConfigurableApplicationContext) { + ((ConfigurableApplicationContext) context).addApplicationListener(indexCreator); + } + } + /** * Returns the default {@link org.springframework.data.mongodb.core.core.convert.MongoConverter}. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java index 84c342d1f..6d78a5e76 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java @@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationListener; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PropertyHandler; +import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.context.MappingContextEvent; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; @@ -169,6 +170,26 @@ public class MongoPersistentEntityIndexCreator implements } } + /** + * Returns whether the current index creator was registered for the given {@link MappingContext}. + * + * @param context + * @return + */ + public boolean isIndexCreatorFor(MappingContext context) { + return this.mappingContext.equals(context); + } + + /** + * Triggers the actual index creation. + * + * @param collection the collection to create the index in + * @param name the name of the index about to be created + * @param indexDefinition the index definition + * @param unique whether it shall be a unique index + * @param dropDups whether to drop duplicates + * @param sparse sparse or not + */ protected void ensureIndex(String collection, String name, DBObject indexDefinition, boolean unique, boolean dropDups, boolean sparse) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java index b972c24e0..ae08ed5ea 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java @@ -15,12 +15,13 @@ */ package org.springframework.data.mongodb.core; -import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.math.BigInteger; +import java.util.Collection; import java.util.Collections; import java.util.regex.Pattern; @@ -31,6 +32,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.context.ApplicationListener; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.convert.converter.Converter; import org.springframework.dao.DataAccessException; @@ -40,6 +42,7 @@ import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.convert.CustomConversions; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.QueryMapper; +import org.springframework.data.mongodb.core.index.MongoPersistentEntityIndexCreator; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; @@ -71,11 +74,13 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { DBCollection collection; MappingMongoConverter converter; + MongoMappingContext mappingContext; @Before public void setUp() { - this.converter = new MappingMongoConverter(factory, new MongoMappingContext()); + this.mappingContext = new MongoMappingContext(); + this.converter = new MappingMongoConverter(factory, mappingContext); this.template = new MongoTemplate(factory, converter); when(factory.getDb()).thenReturn(db); @@ -198,6 +203,29 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests { assertThat(entity.id, is(5)); } + /** + * @see DATAMONGO-533 + */ + @Test + public void registersDefaultEntityIndexCreatorIfApplicationContextHasOneForDifferentMappingContext() { + + GenericApplicationContext applicationContext = new GenericApplicationContext(); + applicationContext.getBeanFactory().registerSingleton("foo", + new MongoPersistentEntityIndexCreator(new MongoMappingContext(), factory)); + + MongoTemplate mongoTemplate = new MongoTemplate(factory, converter); + mongoTemplate.setApplicationContext(applicationContext); + + Collection> listeners = applicationContext.getApplicationListeners(); + assertThat(listeners, hasSize(1)); + + ApplicationListener listener = listeners.iterator().next(); + + assertThat(listener, is(instanceOf(MongoPersistentEntityIndexCreator.class))); + MongoPersistentEntityIndexCreator creator = (MongoPersistentEntityIndexCreator) listener; + assertThat(creator.isIndexCreatorFor(mappingContext), is(true)); + } + class AutogenerateableId { @Id diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java index fd468fda5..95c0816f5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java @@ -54,13 +54,13 @@ public class MongoPersistentEntityIndexCreatorIntegrationTests { } @Test - public void foo() { + public void createsIndexForConfiguredMappingContextOnly() { List indexInfo = templateOne.indexOps(SampleEntity.class).getIndexInfo(); assertThat(indexInfo, hasSize(greaterThan(0))); assertThat(indexInfo, Matchers. hasItem(hasProperty("name", is("prop")))); - indexInfo = templateTwo.indexOps(SampleEntity.class).getIndexInfo(); + indexInfo = templateTwo.indexOps("sampleEntity").getIndexInfo(); assertThat(indexInfo, hasSize(0)); } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index f47eddd44..10c7dc72b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -81,6 +81,20 @@ public class MongoPersistentEntityIndexCreatorUnitTests { assertThat(creator.indexDefinition, is(nullValue())); } + /** + * @see DATAMONGO-530 + */ + @Test + public void isIndexCreatorForMappingContextHandedIntoConstructor() { + + MongoMappingContext mappingContext = new MongoMappingContext(); + mappingContext.initialize(); + + MongoPersistentEntityIndexCreator creator = new DummyMongoPersistentEntityIndexCreator(mappingContext, factory); + assertThat(creator.isIndexCreatorFor(mappingContext), is(true)); + assertThat(creator.isIndexCreatorFor(new MongoMappingContext()), is(false)); + } + static class Person { @Indexed(name = "indexName")