Reorganized how index creation and initial entity registration are handled. It now happens when the context is refreshed and any time entities are registered with addPersistentEntity via synchronous ApplicationEvent dispatching.
This commit is contained in:
@@ -16,27 +16,18 @@
|
||||
|
||||
package org.springframework.data.document.mongodb.config;
|
||||
|
||||
import java.util.HashSet;
|
||||
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.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.Document;
|
||||
import org.springframework.data.document.mongodb.mapping.MappingConfigurationHelper;
|
||||
import org.springframework.data.document.mongodb.mapping.MongoMappingConfigurationBuilder;
|
||||
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
|
||||
import org.springframework.data.document.mongodb.mapping.event.MappingConfigurationListener;
|
||||
import org.springframework.data.document.mongodb.mapping.index.IndexCreationHelper;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
@@ -50,7 +41,7 @@ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final String CONFIGURATION_BUILDER = "mappingConfigurationBuilder";
|
||||
private static final String MAPPING_CONTEXT = "mappingContext";
|
||||
private static final String INDEX_CREATION_HELPER = "indexCreationHelper";
|
||||
private static final String MAPPING_CONFIGURATION_HELPER = "mappingConfigurationHelper";
|
||||
private static final String CONFIGURATION_LISTENER = "mappingConfigurationListener";
|
||||
private static final String TEMPLATE = "mongoTemplate";
|
||||
private static final String BASE_PACKAGE = "base-package";
|
||||
@@ -75,7 +66,6 @@ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser {
|
||||
if (null == ctxRef || "".equals(ctxRef)) {
|
||||
BeanDefinitionBuilder mappingContextBuilder = BeanDefinitionBuilder.genericBeanDefinition(MongoMappingContext.class);
|
||||
mappingContextBuilder.addPropertyReference("mappingConfigurationBuilder", builderRef);
|
||||
mappingContextBuilder.addPropertyValue("indexCreationHelper", new RuntimeBeanReference(INDEX_CREATION_HELPER));
|
||||
registry.registerBeanDefinition(MAPPING_CONTEXT, mappingContextBuilder.getBeanDefinition());
|
||||
ctxRef = MAPPING_CONTEXT;
|
||||
}
|
||||
@@ -96,37 +86,18 @@ public class MongoMappingConverterParser extends AbstractBeanDefinitionParser {
|
||||
converterBuilder.addPropertyReference("mongo", mongoRef);
|
||||
|
||||
try {
|
||||
registry.getBeanDefinition(INDEX_CREATION_HELPER);
|
||||
registry.getBeanDefinition(MAPPING_CONFIGURATION_HELPER);
|
||||
} catch (NoSuchBeanDefinitionException ignored) {
|
||||
String templateRef = element.getAttribute("mongo-template-ref");
|
||||
if (null == templateRef || "".equals(templateRef)) {
|
||||
templateRef = TEMPLATE;
|
||||
}
|
||||
BeanDefinitionBuilder indexListenerBuilder = BeanDefinitionBuilder.genericBeanDefinition(IndexCreationHelper.class);
|
||||
indexListenerBuilder.addPropertyValue("mongoTemplate", new RuntimeBeanReference(templateRef));
|
||||
registry.registerBeanDefinition(INDEX_CREATION_HELPER, indexListenerBuilder.getBeanDefinition());
|
||||
BeanDefinitionBuilder mappingConfigHelperBuilder = BeanDefinitionBuilder.genericBeanDefinition(MappingConfigurationHelper.class);
|
||||
mappingConfigHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(ctxRef));
|
||||
mappingConfigHelperBuilder.addConstructorArgValue(new RuntimeBeanReference(templateRef));
|
||||
registry.registerBeanDefinition(MAPPING_CONFIGURATION_HELPER, mappingConfigHelperBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder listenerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MappingConfigurationListener.class);
|
||||
listenerBuilder.addPropertyReference("mappingContext", ctxRef);
|
||||
|
||||
// Scan for @Document entities
|
||||
String basePackage = element.getAttribute(BASE_PACKAGE);
|
||||
if (null != basePackage) {
|
||||
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||
Set<BeanDefinition> entities = scanner.findCandidateComponents(basePackage);
|
||||
if (null != entities) {
|
||||
Set<String> initialEntitySet = new HashSet<String>(entities.size());
|
||||
for (BeanDefinition def : entities) {
|
||||
initialEntitySet.add(def.getBeanClassName());
|
||||
}
|
||||
listenerBuilder.addPropertyValue("initialEntitySet", initialEntitySet);
|
||||
}
|
||||
}
|
||||
registry.registerBeanDefinition(CONFIGURATION_LISTENER, listenerBuilder.getBeanDefinition());
|
||||
|
||||
return converterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.document.mongodb.mapping.index;
|
||||
package org.springframework.data.document.mongodb.mapping;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
@@ -23,6 +23,7 @@ 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;
|
||||
@@ -34,6 +35,7 @@ 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;
|
||||
@@ -41,32 +43,60 @@ import org.springframework.data.document.mongodb.index.CompoundIndex;
|
||||
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.document.mongodb.mapping.Document;
|
||||
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class IndexCreationHelper implements ApplicationContextAware, InitializingBean {
|
||||
public class MappingConfigurationHelper implements ApplicationListener<MappingContextEvent>, ApplicationContextAware, InitializingBean {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(IndexCreationHelper.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(MappingConfigurationHelper.class);
|
||||
|
||||
private Map<String, CompoundIndex> compoundIndexes = new HashMap<String, CompoundIndex>();
|
||||
private Map<String, Indexed> fieldIndexes = new HashMap<String, Indexed>();
|
||||
private Set<Class<?>> classesSeen = Collections.newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>());
|
||||
private ApplicationContext applicationContext;
|
||||
private MongoMappingContext mappingContext;
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
public IndexCreationHelper() {
|
||||
public MappingConfigurationHelper(MongoMappingContext mappingContext, MongoTemplate mongoTemplate) {
|
||||
this.mappingContext = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MongoMappingContext getMappingContext() {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
public void setMappingContext(MongoMappingContext mappingContext) {
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
public MongoTemplate getMongoTemplate() {
|
||||
@@ -77,7 +107,7 @@ public class IndexCreationHelper implements ApplicationContextAware, Initializin
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
public void checkForIndexes(MongoPersistentEntity<?> entity) {
|
||||
protected void checkForIndexes(MongoPersistentEntity<?> entity) {
|
||||
Class<?> type = entity.getType();
|
||||
if (!classesSeen.contains(type)) {
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -16,36 +16,28 @@
|
||||
|
||||
package org.springframework.data.document.mongodb.mapping;
|
||||
|
||||
import org.springframework.data.document.mongodb.mapping.index.IndexCreationHelper;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.mapping.BasicMappingContext;
|
||||
import org.springframework.data.mapping.model.PersistentEntity;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class MongoMappingContext extends BasicMappingContext {
|
||||
|
||||
protected IndexCreationHelper indexCreationHelper;
|
||||
protected Set<String> initialEntitySet = new HashSet<String>();
|
||||
|
||||
public MongoMappingContext() {
|
||||
builder = new MongoMappingConfigurationBuilder();
|
||||
}
|
||||
|
||||
public IndexCreationHelper getIndexCreationHelper() {
|
||||
return indexCreationHelper;
|
||||
public Set<String> getInitialEntitySet() {
|
||||
return initialEntitySet;
|
||||
}
|
||||
|
||||
public void setIndexCreationHelper(IndexCreationHelper indexCreationHelper) {
|
||||
this.indexCreationHelper = indexCreationHelper;
|
||||
public void setInitialEntitySet(Set<String> initialEntitySet) {
|
||||
this.initialEntitySet = initialEntitySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> PersistentEntity<T> addPersistentEntity(TypeInformation typeInformation) {
|
||||
PersistentEntity<T> entity = super.addPersistentEntity(typeInformation);
|
||||
if (entity instanceof MongoPersistentEntity && null != indexCreationHelper) {
|
||||
indexCreationHelper.checkForIndexes((MongoPersistentEntity<?>) entity);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* 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.document.mongodb.mapping.event;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.document.mongodb.mapping.index.IndexCreationHelper;
|
||||
import org.springframework.data.mapping.event.MappingContextEvent;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class IndexCreationListener implements ApplicationListener<MappingContextEvent>, ApplicationContextAware {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(IndexCreationListener.class);
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
@Autowired
|
||||
private IndexCreationHelper indexCreationHelper;
|
||||
private ExecutorService worker = Executors.newFixedThreadPool(1);
|
||||
private LinkedBlockingQueue<MappingContextEvent> mappingEvents = new LinkedBlockingQueue<MappingContextEvent>();
|
||||
|
||||
public IndexCreationListener() {
|
||||
worker.submit(new IndexCreationWorker());
|
||||
}
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public IndexCreationHelper getIndexCreationHelper() {
|
||||
return indexCreationHelper;
|
||||
}
|
||||
|
||||
public void setIndexCreationHelper(IndexCreationHelper indexCreationHelper) {
|
||||
this.indexCreationHelper = indexCreationHelper;
|
||||
}
|
||||
|
||||
public void onApplicationEvent(MappingContextEvent event) {
|
||||
mappingEvents.add(event);
|
||||
}
|
||||
|
||||
public void cleanUp() throws InterruptedException {
|
||||
while (mappingEvents.size() > 0) {
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
|
||||
private class IndexCreationWorker implements Runnable {
|
||||
public void run() {
|
||||
while (true) {
|
||||
MappingContextEvent event = null;
|
||||
try {
|
||||
event = mappingEvents.take();
|
||||
if (null == applicationContext) {
|
||||
Thread.sleep(500);
|
||||
mappingEvents.add(event);
|
||||
}
|
||||
} catch (InterruptedException ignored) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(ignored.getMessage(), ignored);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (event.getPersistentEntity() instanceof MongoPersistentEntity<?>) {
|
||||
MongoPersistentEntity<?> entity = (MongoPersistentEntity<?>) event.getPersistentEntity();
|
||||
indexCreationHelper.checkForIndexes(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011 by the original author(s).
|
||||
*
|
||||
* 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.document.mongodb.mapping.event;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
*/
|
||||
public class MappingConfigurationListener implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
private MongoMappingContext mappingContext;
|
||||
private Set<String> initialEntitySet;
|
||||
|
||||
public MappingConfigurationListener() {
|
||||
}
|
||||
|
||||
public MongoMappingContext getMappingContext() {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
public void setMappingContext(MongoMappingContext mappingContext) {
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
public Set<String> getInitialEntitySet() {
|
||||
return initialEntitySet;
|
||||
}
|
||||
|
||||
public void setInitialEntitySet(Set<String> initialEntitySet) {
|
||||
this.initialEntitySet = initialEntitySet;
|
||||
}
|
||||
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
for (String className : initialEntitySet) {
|
||||
try {
|
||||
Class<?> clazz = Class.forName(className);
|
||||
if (null == mappingContext.getPersistentEntity(clazz)) {
|
||||
mappingContext.addPersistentEntity(clazz);
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user