Browse Source

DATAMONGO-533 - Fixed index creator registration.

In cases an ApplicationContext already contains a MongoPersistentEntityIndexCreator the default one is not registered, even if the one in the ApplicationContext listens to another MappingContext's events.

Polished iterable classes setup in MongoTemplate along the way. Some JavaDoc polishes as well.
pull/12/head
Oliver Gierke 13 years ago
parent
commit
13a69ecdfd
  1. 55
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  2. 21
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreator.java
  3. 32
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java
  4. 4
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java
  5. 14
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java

55
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.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; 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 Logger LOGGER = LoggerFactory.getLogger(MongoTemplate.class);
private static final String ID = "_id"; private static final String ID = "_id";
private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE; private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE;
@SuppressWarnings("serial") private static final Collection<String> ITERABLE_CLASSES;
private static final List<String> ITERABLE_CLASSES = new ArrayList<String>() {
{ static {
add(List.class.getName());
add(Collection.class.getName()); Set<String> iterableClasses = new HashSet<String>();
add(Iterator.class.getName()); 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. * 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; this.readPreference = readPreference;
} }
/*
* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
String[] beans = applicationContext.getBeanNamesForType(MongoPersistentEntityIndexCreator.class);
if ((null == beans || beans.length == 0) && applicationContext instanceof ConfigurableApplicationContext) { prepareIndexCreator(applicationContext);
((ConfigurableApplicationContext) applicationContext).addApplicationListener(indexCreator);
}
eventPublisher = applicationContext; eventPublisher = applicationContext;
if (mappingContext instanceof ApplicationEventPublisherAware) { if (mappingContext instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher); ((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
@ -259,6 +266,30 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
resourceLoader = applicationContext; 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}. * Returns the default {@link org.springframework.data.mongodb.core.core.convert.MongoConverter}.
* *

21
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.context.ApplicationListener;
import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PropertyHandler; import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.MappingContextEvent; import org.springframework.data.mapping.context.MappingContextEvent;
import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; 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, protected void ensureIndex(String collection, String name, DBObject indexDefinition, boolean unique,
boolean dropDups, boolean sparse) { boolean dropDups, boolean sparse) {

32
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUnitTests.java

@ -15,12 +15,13 @@
*/ */
package org.springframework.data.mongodb.core; package org.springframework.data.mongodb.core;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.Matchers.*; import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -31,6 +32,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Mockito; import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.dao.DataAccessException; 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.CustomConversions;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.QueryMapper; 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.mapping.MongoMappingContext;
import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.core.query.Update;
@ -71,11 +74,13 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
DBCollection collection; DBCollection collection;
MappingMongoConverter converter; MappingMongoConverter converter;
MongoMappingContext mappingContext;
@Before @Before
public void setUp() { 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); this.template = new MongoTemplate(factory, converter);
when(factory.getDb()).thenReturn(db); when(factory.getDb()).thenReturn(db);
@ -198,6 +203,29 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
assertThat(entity.id, is(5)); 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<ApplicationListener<?>> 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 { class AutogenerateableId {
@Id @Id

4
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorIntegrationTests.java

@ -54,13 +54,13 @@ public class MongoPersistentEntityIndexCreatorIntegrationTests {
} }
@Test @Test
public void foo() { public void createsIndexForConfiguredMappingContextOnly() {
List<IndexInfo> indexInfo = templateOne.indexOps(SampleEntity.class).getIndexInfo(); List<IndexInfo> indexInfo = templateOne.indexOps(SampleEntity.class).getIndexInfo();
assertThat(indexInfo, hasSize(greaterThan(0))); assertThat(indexInfo, hasSize(greaterThan(0)));
assertThat(indexInfo, Matchers.<IndexInfo> hasItem(hasProperty("name", is("prop")))); assertThat(indexInfo, Matchers.<IndexInfo> hasItem(hasProperty("name", is("prop"))));
indexInfo = templateTwo.indexOps(SampleEntity.class).getIndexInfo(); indexInfo = templateTwo.indexOps("sampleEntity").getIndexInfo();
assertThat(indexInfo, hasSize(0)); assertThat(indexInfo, hasSize(0));
} }
} }

14
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())); 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 { static class Person {
@Indexed(name = "indexName") @Indexed(name = "indexName")

Loading…
Cancel
Save