From 67b5a1c99bdbb11cd2e1fd839aaee4eecdc169be Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Tue, 22 Mar 2011 21:07:19 +0100 Subject: [PATCH] Tweaks to index creation handling. Renamed MappingConfigurationHelper to MongoPersistentEntityIndexCreator as this is the purpose of the class. Refactored it not be ApplicationContextAware, Initializing bean but rather simply use the injected MongoMappingContext and MongoTemplate to trigger index creation. Added base-package parsing for entities annotated with @Persistent and @Document to be added to the MappingContext. Moved createPersistentEntity and createPersistentProperty methods into MongoMappingContext. --- .../config/MongoMappingConverterParser.java | 48 ++++++++++--- .../MongoMappingConfigurationBuilder.java | 17 ----- .../mongodb/mapping/MongoMappingContext.java | 35 ++++++---- ...=> MongoPersistentEntityIndexCreator.java} | 70 +++++-------------- ...rsonRepositoryIntegrationTests-context.xml | 2 +- 5 files changed, 80 insertions(+), 92 deletions(-) rename spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/{MappingConfigurationHelper.java => MongoPersistentEntityIndexCreator.java} (71%) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoMappingConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoMappingConverterParser.java index 93d3c7a2b..e82979670 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoMappingConverterParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MongoMappingConverterParser.java @@ -16,26 +16,32 @@ package org.springframework.data.document.mongodb.config; +import java.util.Set; + import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.ManagedSet; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.data.annotation.Persistent; import org.springframework.data.document.mongodb.convert.MappingMongoConverter; -import org.springframework.data.document.mongodb.mapping.MappingConfigurationHelper; +import org.springframework.data.document.mongodb.mapping.Document; +import org.springframework.data.document.mongodb.mapping.MongoPersistentEntityIndexCreator; import org.springframework.data.document.mongodb.mapping.MongoMappingConfigurationBuilder; import org.springframework.data.document.mongodb.mapping.MongoMappingContext; +import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** - * Created by IntelliJ IDEA. - * User: jbrisbin - * Date: 2/28/11 - * Time: 9:26 AM - * To change this template use File | Settings | File Templates. + * @author Jon Brisbin + * @author Oliver Gierke */ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser { @@ -65,6 +71,12 @@ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser { String ctxRef = element.getAttribute("mapping-context-ref"); if (null == ctxRef || "".equals(ctxRef)) { BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoMappingContext.class); + + Set classesToAdd = getInititalEntityClasses(element, mappingContextBuilder); + if (classesToAdd != null) { + mappingContextBuilder.addPropertyValue("initialEntitySet", classesToAdd); + } + mappingContextBuilder.addPropertyReference("mappingConfigurationBuilder", builderRef); registry.registerBeanDefinition(MAPPING_CONTEXT, mappingContextBuilder.getBeanDefinition()); ctxRef = MAPPING_CONTEXT; @@ -92,7 +104,7 @@ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser { if (null == templateRef || "".equals(templateRef)) { templateRef = TEMPLATE; } - BeanDefinitionBuilder mappingConfigHelperBuilder = BeanDefinitionBuilder.genericBeanDefinition(MappingConfigurationHelper.class); + BeanDefinitionBuilder mappingConfigHelperBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoPersistentEntityIndexCreator.class); mappingConfigHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(ctxRef)); mappingConfigHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(templateRef)); registry.registerBeanDefinition(MAPPING_CONFIGURATION_HELPER, mappingConfigHelperBuilder.getBeanDefinition()); @@ -100,5 +112,25 @@ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser { return converterBuilder.getBeanDefinition(); } - + + + public Set getInititalEntityClasses(Element element, BeanDefinitionBuilder builder) { + + String basePackage = element.getAttribute(BASE_PACKAGE); + + if (!StringUtils.hasText(basePackage)) { + return null; + } + + ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false); + componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class)); + componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class)); + + Set classes = new ManagedSet(); + for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) { + classes.add(candidate.getBeanClassName()); + } + + return classes; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingConfigurationBuilder.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingConfigurationBuilder.java index c75f4794c..6b94eda13 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingConfigurationBuilder.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingConfigurationBuilder.java @@ -25,10 +25,6 @@ import org.bson.types.ObjectId; import org.springframework.data.mapping.BasicMappingConfigurationBuilder; import org.springframework.data.mapping.MappingBeanHelper; import org.springframework.data.mapping.model.MappingConfigurationException; -import org.springframework.data.mapping.model.MappingContext; -import org.springframework.data.mapping.model.PersistentEntity; -import org.springframework.data.mapping.model.PersistentProperty; -import org.springframework.data.util.TypeInformation; /** * @author Jon Brisbin @@ -47,19 +43,6 @@ public class MongoMappingConfigurationBuilder extends BasicMappingConfigurationB simpleTypes.add(CodeWScope.class); } - @Override - public PersistentProperty createPersistentProperty(Field field, - PropertyDescriptor descriptor, - TypeInformation information) throws MappingConfigurationException { - return new MongoPersistentProperty(field, descriptor, information); - } - - @Override - public PersistentEntity createPersistentEntity(TypeInformation typeInformation, - MappingContext mappingContext) throws MappingConfigurationException { - return new MongoPersistentEntity(mappingContext, typeInformation); - } - @Override public boolean isAssociation(Field field, PropertyDescriptor descriptor) throws MappingConfigurationException { if (field.isAnnotationPresent(DBRef.class)) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingContext.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingContext.java index dabeca864..11752d799 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingContext.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoMappingContext.java @@ -16,28 +16,39 @@ package org.springframework.data.document.mongodb.mapping; -import java.util.HashSet; -import java.util.Set; - +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.util.Collection; import org.springframework.data.mapping.BasicMappingContext; +import org.springframework.data.mapping.model.MappingConfigurationException; +import org.springframework.data.mapping.model.MappingContext; +import org.springframework.data.mapping.model.PersistentEntity; +import org.springframework.data.mapping.model.PersistentProperty; +import org.springframework.data.util.TypeInformation; /** * @author Jon Brisbin + * @author Oliver Gierke */ public class MongoMappingContext extends BasicMappingContext { - protected Set initialEntitySet = new HashSet(); - - public MongoMappingContext() { - builder = new MongoMappingConfigurationBuilder(); + /* (non-Javadoc) + * @see org.springframework.data.mapping.BasicMappingContext#getPersistentEntities() + */ + @Override + public Collection> getPersistentEntities() { + return (Collection>) super.getPersistentEntities(); } - public Set getInitialEntitySet() { - return initialEntitySet; + @Override + public PersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, + TypeInformation information) throws MappingConfigurationException { + return new MongoPersistentProperty(field, descriptor, information); } - public void setInitialEntitySet(Set initialEntitySet) { - this.initialEntitySet = initialEntitySet; + @Override + public PersistentEntity createPersistentEntity(TypeInformation typeInformation, MappingContext mappingContext) + throws MappingConfigurationException { + return new MongoPersistentEntity(mappingContext, typeInformation); } - } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MappingConfigurationHelper.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java similarity index 71% rename from spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MappingConfigurationHelper.java rename to spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java index c347d2b63..234fb9539 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MappingConfigurationHelper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/MongoPersistentEntityIndexCreator.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import com.google.code.morphia.mapping.MappingException; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBObject; @@ -31,11 +30,6 @@ import com.mongodb.MongoException; import com.mongodb.util.JSON; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ApplicationListener; import org.springframework.dao.DataAccessException; import org.springframework.data.document.mongodb.CollectionCallback; import org.springframework.data.document.mongodb.MongoTemplate; @@ -44,69 +38,37 @@ import org.springframework.data.document.mongodb.index.CompoundIndexes; import org.springframework.data.document.mongodb.index.IndexDirection; import org.springframework.data.document.mongodb.index.Indexed; import org.springframework.data.mapping.PropertyHandler; -import org.springframework.data.mapping.event.MappingContextEvent; -import org.springframework.data.mapping.model.PersistentEntity; import org.springframework.data.mapping.model.PersistentProperty; +import org.springframework.util.Assert; /** + * Component that inspects {@link MongoPersistentEntity} instances contained in the given {@link MongoMappingContext} + * for indexing metadata and ensures the indexes to be available. + * * @author Jon Brisbin + * @author Oliver Gierke */ -public class MappingConfigurationHelper implements ApplicationListener, ApplicationContextAware, InitializingBean { +public class MongoPersistentEntityIndexCreator { - private static final Logger log = LoggerFactory.getLogger(MappingConfigurationHelper.class); + private static final Logger log = LoggerFactory.getLogger(MongoPersistentEntityIndexCreator.class); private Map compoundIndexes = new HashMap(); private Map fieldIndexes = new HashMap(); private Set> classesSeen = Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); - private ApplicationContext applicationContext; - private MongoMappingContext mappingContext; - private MongoTemplate mongoTemplate; + + private final MongoTemplate mongoTemplate; - public MappingConfigurationHelper(MongoMappingContext mappingContext, MongoTemplate mongoTemplate) { - this.mappingContext = mappingContext; + public MongoPersistentEntityIndexCreator(MongoMappingContext mappingContext, MongoTemplate mongoTemplate) { + + Assert.notNull(mongoTemplate); + Assert.notNull(mappingContext); this.mongoTemplate = mongoTemplate; - } - - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.applicationContext = applicationContext; - } - - public void onApplicationEvent(MappingContextEvent event) { - PersistentEntity entity = event.getPersistentEntity(); - if (entity instanceof MongoPersistentEntity) { - checkForIndexes((MongoPersistentEntity) entity); - } - } - - public void afterPropertiesSet() throws Exception { - for (String className : mappingContext.getInitialEntitySet()) { - try { - Class clazz = Class.forName(className); - if (null == mappingContext.getPersistentEntity(clazz)) { - mappingContext.addPersistentEntity(clazz); - } - } catch (ClassNotFoundException e) { - throw new MappingException(e.getMessage(), e); - } + + for (MongoPersistentEntity entity : mappingContext.getPersistentEntities()) { + checkForIndexes(entity); } } - public MongoMappingContext getMappingContext() { - return mappingContext; - } - - public void setMappingContext(MongoMappingContext mappingContext) { - this.mappingContext = mappingContext; - } - - public MongoTemplate getMongoTemplate() { - return mongoTemplate; - } - - public void setMongoTemplate(MongoTemplate mongoTemplate) { - this.mongoTemplate = mongoTemplate; - } - protected void checkForIndexes(MongoPersistentEntity entity) { Class type = entity.getType(); if (!classesSeen.contains(type)) { diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml index ddc714bfb..9483517e6 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/repository/PersonRepositoryIntegrationTests-context.xml @@ -11,7 +11,7 @@ - +