DATADOC-143 - Made MongoMappingContext the default converter for the template, which also meant:

Several changes to how objects are initialized inside the template:

1. In one is not specified, a MappingMongoConverter is created and set as the default.
2. A special ApplicationEventPublisher implementation is installed by default to handle creating indexes when the template isn't used inside a Spring application context.
3. If a Spring application context is available, it will be set as the template's application context and eventPublisher, with the index creator being registered as an event listener if one isn't already present.

The tests had to be changed in a couple places to accurately reflect how mapping contexts and converters are now handled.
This commit is contained in:
J. Brisbin
2011-05-20 11:36:17 -05:00
parent 98da8beb67
commit ad287efb4e
17 changed files with 208 additions and 229 deletions

View File

@@ -40,8 +40,12 @@ import com.mongodb.util.JSON;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.types.ObjectId;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
@@ -51,6 +55,7 @@ import org.springframework.data.document.mongodb.convert.MongoConverter;
import org.springframework.data.document.mongodb.index.IndexDefinition;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntityIndexCreator;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.document.mongodb.mapping.event.AfterConvertEvent;
import org.springframework.data.document.mongodb.mapping.event.AfterLoadEvent;
@@ -76,7 +81,7 @@ import org.springframework.util.Assert;
* @author Mark Pollack
* @author Oliver Gierke
*/
public class MongoTemplate implements MongoOperations, ApplicationEventPublisherAware {
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
private static final Log LOGGER = LogFactory.getLog(MongoTemplate.class);
@@ -99,13 +104,15 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
*/
private boolean slaveOk = false;
private final MongoConverter mongoConverter;
private final MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private final MongoDbFactory mongoDbFactory;
private final MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
private final QueryMapper mapper;
private MongoConverter mongoConverter;
private MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext;
private MongoDbFactory mongoDbFactory;
private MongoExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
private QueryMapper mapper;
private ApplicationContext applicationContext;
private ApplicationEventPublisher eventPublisher;
private MongoPersistentEntityIndexCreator indexCreator;
/**
* Constructor used for a basic template configuration
@@ -114,7 +121,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* @param databaseName
*/
public MongoTemplate(Mongo mongo, String databaseName) {
this(new MongoDbFactoryBean(mongo, databaseName));
this(new MongoDbFactoryBean(mongo, databaseName), null, null, null);
}
/**
@@ -126,7 +133,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* @param mongoConverter
*/
public MongoTemplate(Mongo mongo, String databaseName, MongoConverter mongoConverter) {
this(new MongoDbFactoryBean(mongo, databaseName), mongoConverter);
this(new MongoDbFactoryBean(mongo, databaseName), mongoConverter, null, null);
}
/**
@@ -135,7 +142,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* @param mongoDbFactory
*/
public MongoTemplate(MongoDbFactory mongoDbFactory) {
this(mongoDbFactory, null);
this(mongoDbFactory, null, null, null);
}
/**
@@ -162,37 +169,52 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
WriteConcern writeConcern,
WriteResultChecking writeResultChecking) {
Assert.notNull(mongoDbFactory);
// Always need a MongoDbFactory for obtaining instances of DB
this.mongoDbFactory = mongoDbFactory;
this.mongoConverter = mongoConverter == null ? getDefaultMongoConverter() : mongoConverter;
this.writeConcern = writeConcern;
if (this.mongoConverter instanceof MappingMongoConverter) {
initializeMappingMongoConverter((MappingMongoConverter) this.mongoConverter);
// Conversion of DBObject to POJO handled either custom or by default (MappingMongoConverter)
if (null == mongoConverter) {
this.mongoConverter = getDefaultMongoConverter();
} else {
this.mongoConverter = mongoConverter;
}
this.mappingContext = this.mongoConverter.getMappingContext();
this.mapper = new QueryMapper(this.mongoConverter);
// We always have a mapping context in the converter, whether it's a simple one or not
mappingContext = this.mongoConverter.getMappingContext();
// We create indexes based on mapping events
if (null != mappingContext && mappingContext instanceof MongoMappingContext) {
indexCreator = new MongoPersistentEntityIndexCreator((MongoMappingContext) mappingContext, mongoDbFactory);
eventPublisher = new MongoMappingEventPublisher(indexCreator);
if (mappingContext instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
}
}
// WriteConcern
this.writeConcern = writeConcern;
// For converting ID names and values throughout Query objects
mapper = new QueryMapper(this.mongoConverter);
// Track WriteResults?
if (writeResultChecking != null) {
this.writeResultChecking = writeResultChecking;
}
if (this.mappingContext instanceof MongoMappingContext) {
this.eventPublisher = new MongoMappingEventPublisher((MongoMappingContext) mappingContext, mongoDbFactory);
}
}
private final MongoConverter getDefaultMongoConverter() {
//ToDo: maybe add some additional configurations to this very basic one
MappingMongoConverter converter = new MappingMongoConverter(new MongoMappingContext());
MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory, new MongoMappingContext());
converter.afterPropertiesSet();
return converter;
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
String[] beans = applicationContext.getBeanNamesForType(MongoPersistentEntityIndexCreator.class);
if ((null == beans || beans.length == 0) && applicationContext instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) applicationContext).addApplicationListener(indexCreator);
}
eventPublisher = applicationContext;
if (mappingContext instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) mappingContext).setApplicationEventPublisher(eventPublisher);
}
}
/**
@@ -213,9 +235,13 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return this.mongoDbFactory;
}
public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> getMappingContext() {
return mappingContext;
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#getDefaultCollectionName()
*/
* @see org.springframework.data.document.mongodb.MongoOperations#getDefaultCollectionName()
*/
public String getCollectionName(Class<?> clazz) {
return this.determineCollectionName(clazz);
}
@@ -417,12 +443,12 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
public <T> List<T> find(String collectionName, Query query, Class<T> targetClass, CursorPreparer preparer) {
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), targetClass, preparer);
}
public <T> T findById(Object id, Class<T> targetClass) {
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(targetClass);
return findById(persistentEntity.getCollection(), id, targetClass);
}
public <T> T findById(String collectionName, Object id, Class<T> targetClass) {
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(targetClass);
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
@@ -455,15 +481,15 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
public void insert(String collectionName, Object objectToSave) {
doInsert(collectionName, objectToSave, this.mongoConverter);
}
/**
* Prepare the collection before any processing is done using it. This allows a convenient way to apply
* Prepare the collection before any processing is done using it. This allows a convenient way to apply
* settings like slaveOk() etc. Can be overridden in sub-classes.
*
*
* @param collection
*/
protected void prepareCollection(DBCollection collection) {
if(this.slaveOk) {
if (this.slaveOk) {
collection.slaveOk();
}
}
@@ -975,7 +1001,7 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
throw new MappingException(e.getMessage(), e);
}
}
protected String getIdPropertyName(Object object) {
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(object.getClass());
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
@@ -1027,18 +1053,15 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* <li>Execute the given {@link ConnectionCallback} for a {@link DBObject}.</li>
* <li>Apply the given {@link DbObjectCallback} to each of the {@link DBObject}s to obtain the result.</li>
* <ol>
*
*
* @param <T>
* @param collectionCallback
* the callback to retrieve the {@link DBObject} with
* @param objectCallback
* the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName
* the collection to be queried
* @param collectionCallback the callback to retrieve the {@link DBObject} with
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName the collection to be queried
* @return
*/
private <T> T executeFindOneInternal(CollectionCallback<DBObject> collectionCallback, DbObjectCallback<T> objectCallback,
String collectionName) {
String collectionName) {
try {
T result = objectCallback.doWith(collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName)));
@@ -1058,20 +1081,16 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
* <li>Iterate over the {@link DBCursor} and applies the given {@link DbObjectCallback} to each of the
* {@link DBObject}s collecting the actual result {@link List}.</li>
* <ol>
*
*
* @param <T>
* @param collectionCallback
* the callback to retrieve the {@link DBCursor} with
* @param preparer
* the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
* @param objectCallback
* the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName
* the collection to be queried
* @param collectionCallback the callback to retrieve the {@link DBCursor} with
* @param preparer the {@link CursorPreparer} to potentially modify the {@link DBCursor} before ireating over it
* @param objectCallback the {@link DbObjectCallback} to transform {@link DBObject}s into the actual domain type
* @param collectionName the collection to be queried
* @return
*/
private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collectionCallback, CursorPreparer preparer,
DbObjectCallback<T> objectCallback, String collectionName) {
DbObjectCallback<T> objectCallback, String collectionName) {
try {
DBCursor cursor = collectionCallback.doInCollection(getAndPrepareCollection(getDb(), collectionName));
@@ -1179,11 +1198,6 @@ public class MongoTemplate implements MongoOperations, ApplicationEventPublisher
return resolved == null ? ex : resolved;
}
private void initializeMappingMongoConverter(MappingMongoConverter converter) {
converter.setMongo(this.mongoDbFactory.getMongo());
converter.setDefaultDatabase(this.mongoDbFactory.getDatabaseName());
}
/**
* Simple {@link CollectionCallback} that takes a query {@link DBObject} plus an optional fields specification
* {@link DBObject} and executes that against the {@link DBCollection}.

View File

@@ -31,7 +31,6 @@ import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.convert.MappingMongoConverter;
import org.springframework.data.document.mongodb.mapping.Document;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntityIndexCreator;
import org.springframework.data.mapping.context.MappingContextAwareBeanPostProcessor;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -39,29 +38,27 @@ import org.springframework.util.StringUtils;
@Configuration
public abstract class AbstractMongoConfiguration {
public abstract String defaultDatabaseName();
@Bean
public abstract Mongo mongo() throws Exception;
@Bean
public abstract MongoTemplate mongoTemplate() throws Exception;
public String defaultDatabaseName() {
return "db";
}
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new MongoDbFactoryBean(mongo(), defaultDatabaseName());
}
public String getMappingBasePackage() {
public String mappingBasePackage() {
return "";
}
@Bean
public MongoMappingContext mongoMappingContext() throws ClassNotFoundException, LinkageError {
MongoMappingContext mappingContext = new MongoMappingContext();
String basePackage = getMappingBasePackage();
String basePackage = mappingBasePackage();
if (StringUtils.hasText(basePackage)) {
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
@@ -78,8 +75,7 @@ public abstract class AbstractMongoConfiguration {
@Bean
public MappingMongoConverter mappingMongoConverter() throws Exception {
MappingMongoConverter converter = new MappingMongoConverter(mongoMappingContext());
converter.setMongo(mongo());
MappingMongoConverter converter = new MappingMongoConverter(mongoDbFactory(), mongoMappingContext());
afterMappingMongoConverterCreation(converter);
return converter;
}
@@ -99,8 +95,4 @@ public abstract class AbstractMongoConfiguration {
return bpp;
}
@Bean MongoPersistentEntityIndexCreator mongoPersistentEntityIndexCreator() throws Exception {
MongoPersistentEntityIndexCreator indexCreator = new MongoPersistentEntityIndexCreator(mongoMappingContext(), mongoDbFactory());
return indexCreator;
}
}

View File

@@ -92,16 +92,15 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
converterBuilder.addConstructorArgReference(ctxRef);
// Need a reference to a Mongo instance
String mongoRef = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(mongoRef)) {
mongoRef = MONGO;
String dbFactoryRef = element.getAttribute("db-factory-ref");
if (!StringUtils.hasText(dbFactoryRef)) {
dbFactoryRef = DB_FACTORY;
}
converterBuilder.addPropertyReference("mongo", mongoRef);
converterBuilder.addPropertyReference("mongoDbFactory", dbFactoryRef);
try {
registry.getBeanDefinition(INDEX_HELPER);
} catch (NoSuchBeanDefinitionException ignored) {
String dbFactoryRef = element.getAttribute("db-factory-ref");
if (!StringUtils.hasText(dbFactoryRef)) {
dbFactoryRef = DB_FACTORY;
}

View File

@@ -87,9 +87,9 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
Element mongoEl = DomUtils.getChildElementByTagName(element, "mongo");
if (null != mongoEl) {
String overrideHost = mongoEl.getAttribute("host");
mongoBuilder.addPropertyValue("host", (overrideHost != null ? overrideHost : host));
mongoBuilder.addPropertyValue("host", (StringUtils.hasText(overrideHost) ? overrideHost : host));
String overridePort = mongoEl.getAttribute("port");
mongoBuilder.addPropertyValue("port", (overridePort != null ? overridePort : port));
mongoBuilder.addPropertyValue("port", (StringUtils.hasText(overridePort) ? overridePort : port));
new MongoParser().parseOptions(parserContext, mongoEl, mongoBuilder);
}
registry.registerBeanDefinition(MONGO, mongoBuilder.getBeanDefinition());

View File

@@ -38,7 +38,6 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.DBRef;
import com.mongodb.Mongo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bson.types.ObjectId;
@@ -54,6 +53,7 @@ import org.springframework.core.convert.converter.ConverterFactory;
import org.springframework.core.convert.converter.GenericConverter.ConvertiblePair;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.document.mongodb.MongoDbFactory;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import org.springframework.data.document.mongodb.mapping.MongoPersistentProperty;
import org.springframework.data.mapping.AssociationHandler;
@@ -68,22 +68,23 @@ import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.StringUtils;
/**
* {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
* {@link DBObject}.
*
*
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, InitializingBean {
public static final String CUSTOM_TYPE_KEY = "_class";
@SuppressWarnings({ "unchecked" })
@SuppressWarnings({"unchecked"})
private static final List<Class<?>> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class,
DBObject.class);
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[] { ObjectId.class, String.class,
BigInteger.class, byte[].class });
private static final List<Class<?>> VALID_ID_TYPES = Arrays.asList(new Class<?>[]{ObjectId.class, String.class,
BigInteger.class, byte[].class});
protected static final Log log = LogFactory.getLog(MappingMongoConverter.class);
protected final GenericConversionService conversionService = ConversionServiceFactory
@@ -93,12 +94,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
protected SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
protected ApplicationContext applicationContext;
protected boolean useFieldAccessOnly = true;
protected Mongo mongo;
protected String defaultDatabase;
protected MongoDbFactory mongoDbFactory;
public MappingMongoConverter(MongoDbFactory mongoDbFactory, MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentProperty> mappingContext) {
this.mongoDbFactory = mongoDbFactory;
this.mappingContext = mappingContext;
}
/**
* Creates a new {@link MappingMongoConverter} with the given {@link MappingContext}.
*
*
* @param mappingContext
*/
public MappingMongoConverter(
@@ -110,7 +115,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Add custom {@link Converter} or {@link ConverterFactory} instances to be used that will take presidence over
* metadata driven conversion between of objects to/from DBObject
*
*
* @param converters
*/
public void setCustomConverters(Set<?> converters) {
@@ -124,7 +129,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Inspects the given {@link Converter} for the types it can convert and registers the pair for custom type conversion
* in case the target type is a Mongo basic type.
*
*
* @param converter
*/
private void registerConverter(Object converter) {
@@ -165,12 +170,8 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
return mappingContext;
}
public void setMongo(Mongo mongo) {
this.mongo = mongo;
}
public void setDefaultDatabase(String defaultDatabase) {
this.defaultDatabase = defaultDatabase;
public void setMongoDbFactory(MongoDbFactory mongoDbFactory) {
this.mongoDbFactory = mongoDbFactory;
}
public boolean isUseFieldAccessOnly() {
@@ -246,7 +247,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
spelCtx.setBeanResolver(new BeanFactoryResolver(applicationContext));
}
if (!(dbo instanceof BasicDBList)) {
String[] keySet = dbo.keySet().toArray(new String[] {});
String[] keySet = dbo.keySet().toArray(new String[]{});
for (String key : keySet) {
spelCtx.setVariable(key, dbo.get(key));
}
@@ -255,32 +256,32 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
final List<String> ctorParamNames = new ArrayList<String>();
final MongoPersistentProperty idProperty = entity.getIdProperty();
final S instance = constructInstance(entity, new PreferredConstructor.ParameterValueProvider() {
@SuppressWarnings("unchecked")
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
String name = parameter.getName();
TypeInformation<T> type = parameter.getType();
Class<T> rawType = parameter.getRawType();
String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getKey() : name;
Object obj = dbo.get(key);
@SuppressWarnings("unchecked")
public <T> T getParameterValue(PreferredConstructor.Parameter<T> parameter) {
String name = parameter.getName();
TypeInformation<T> type = parameter.getType();
Class<T> rawType = parameter.getRawType();
String key = idProperty == null ? name : idProperty.getName().equals(name) ? idProperty.getKey() : name;
Object obj = dbo.get(key);
ctorParamNames.add(name);
if (obj instanceof DBRef) {
return read(type, ((DBRef) obj).fetch());
} else if (obj instanceof BasicDBList) {
BasicDBList objAsDbList = (BasicDBList) obj;
List<?> l = unwrapList(objAsDbList, type);
return conversionService.convert(l, rawType);
} else if (obj instanceof DBObject) {
return read(type, ((DBObject) obj));
} else if (null != obj && obj.getClass().isAssignableFrom(rawType)) {
return (T) obj;
} else if (null != obj) {
return conversionService.convert(obj, rawType);
}
ctorParamNames.add(name);
if (obj instanceof DBRef) {
return read(type, ((DBRef) obj).fetch());
} else if (obj instanceof BasicDBList) {
BasicDBList objAsDbList = (BasicDBList) obj;
List<?> l = unwrapList(objAsDbList, type);
return conversionService.convert(l, rawType);
} else if (obj instanceof DBObject) {
return read(type, ((DBObject) obj));
} else if (null != obj && obj.getClass().isAssignableFrom(rawType)) {
return (T) obj;
} else if (null != obj) {
return conversionService.convert(obj, rawType);
}
return null;
}
}, spelCtx);
return null;
}
}, spelCtx);
// Set properties not already set in the constructor
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
@@ -325,7 +326,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Root entry method into write conversion. Adds a type discriminator to the {@link DBObject}. Shouldn't be called for
* nested conversions.
*
*
* @see org.springframework.data.document.mongodb.MongoWriter#write(java.lang.Object, com.mongodb.DBObject)
*/
public void write(final Object obj, final DBObject dbo) {
@@ -345,7 +346,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Internal write conversion method which should be used for nested invocations.
*
*
* @param obj
* @param dbo
*/
@@ -471,7 +472,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
setConversionService(conversionService);
}
@SuppressWarnings({ "unchecked" })
@SuppressWarnings({"unchecked"})
protected void writePropertyInternal(MongoPersistentProperty prop, Object obj, DBObject dbo) {
org.springframework.data.document.mongodb.mapping.DBRef dbref = prop.getField().getAnnotation(
org.springframework.data.document.mongodb.mapping.DBRef.class);
@@ -580,16 +581,16 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
}
}
/**
* Writes the given simple value to the given {@link DBObject}. Will store enum names for enum values.
*
*
* @param key
* @param value
* @param dbObject
*/
private void writeSimpleInternal(String key, Object value, DBObject dbObject) {
Object valueToSet = value.getClass().isEnum() ? ((Enum<?>) value).name() : value;
dbObject.put(key, valueToSet);
}
@@ -619,17 +620,13 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
}
String dbname = dbref.db();
if ("".equals(dbname)) {
dbname = defaultDatabase;
}
DB db = mongo.getDB(dbname);
DB db = StringUtils.hasText(dbname) ? mongoDbFactory.getMongo().getDB(dbname) : mongoDbFactory.getDb();
return new DBRef(db, collection, id);
}
@SuppressWarnings({ "unchecked" })
@SuppressWarnings({"unchecked"})
protected Object getValueInternal(MongoPersistentProperty prop, DBObject dbo, StandardEvaluationContext ctx,
String spelExpr) {
String spelExpr) {
Object o;
if (null != spelExpr) {
@@ -716,7 +713,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Returns the type to be used to convert the DBObject given to.
*
*
* @param dbObject
* @return
*/
@@ -737,7 +734,7 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
/**
* Inspects the a custom class definition stored inside the given {@link DBObject} and returns that in case it's a
* subtype of the given basic one.
*
*
* @param dbObject
* @param basicType
* @return

View File

@@ -142,8 +142,13 @@ public class MongoPersistentEntityIndexCreator implements ApplicationListener<Ma
}
protected void ensureIndex(String collection, final String name, final String def, final IndexDirection direction,
final boolean unique, final boolean dropDups, final boolean sparse) {
protected void ensureIndex(String collection,
final String name,
final String def,
final IndexDirection direction,
final boolean unique,
final boolean dropDups,
final boolean sparse) {
DBObject defObj;
if (null != def) {
defObj = (DBObject) JSON.parse(def);

View File

@@ -18,8 +18,6 @@ package org.springframework.data.document.mongodb.mapping.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.document.mongodb.MongoDbFactory;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntityIndexCreator;
import org.springframework.data.mapping.event.MappingContextEvent;
@@ -30,8 +28,8 @@ public class MongoMappingEventPublisher implements ApplicationEventPublisher {
private MongoPersistentEntityIndexCreator indexCreator;
public MongoMappingEventPublisher(MongoMappingContext mappingContext, MongoDbFactory mongoDbFactory) {
indexCreator = new MongoPersistentEntityIndexCreator(mappingContext, mongoDbFactory);
public MongoMappingEventPublisher(MongoPersistentEntityIndexCreator indexCreator) {
this.indexCreator = indexCreator;
}
public void publishEvent(ApplicationEvent event) {

View File

@@ -15,17 +15,21 @@
*/
package org.springframework.data.document.mongodb;
import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.document.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.document.mongodb.mapping.event.LoggingEventListener;
import org.springframework.data.document.mongodb.mapping.event.MongoMappingEvent;
import com.mongodb.Mongo;
@Configuration
public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
@Override
public String defaultDatabaseName() {
return "geospatial";
}
@Bean
public Mongo mongo() throws Exception {
return new Mongo("localhost");
@@ -33,7 +37,7 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "geospatial", mappingMongoConverter());
return new MongoTemplate(mongoDbFactory());
}
@Bean
@@ -41,7 +45,8 @@ public class GeoSpatialAppConfig extends AbstractMongoConfiguration {
return new LoggingEventListener<MongoMappingEvent>();
}
public String getMappingBasePackage() {
@Override
public String mappingBasePackage() {
return "org.springframework.data.document.mongodb";
}

View File

@@ -43,10 +43,6 @@ import com.mongodb.MongoException;
@ContextConfiguration("classpath:template-mapping.xml")
public class MongoTemplateMappingTests {
@Autowired
@Qualifier("mongoTemplate")
MongoTemplate template0;
@Autowired
@Qualifier("mongoTemplate1")
MongoTemplate template1;
@@ -63,14 +59,6 @@ public class MongoTemplateMappingTests {
template1.dropCollection(template1.getCollectionName(Person.class));
}
@Test
public void insertsEntityCorrectly0() throws Exception {
addAndRetrievePerson(template0);
checkPersonPersisted(template0);
}
@Test
public void insertsEntityCorrectly1() throws Exception {

View File

@@ -15,20 +15,20 @@
*/
package org.springframework.data.document.mongodb;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.springframework.data.document.mongodb.query.Criteria.where;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.document.mongodb.query.Criteria.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.WriteResult;
import org.bson.types.ObjectId;
import org.junit.Assert;
import org.junit.Before;
@@ -52,15 +52,9 @@ import org.springframework.data.document.mongodb.query.Update;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.WriteResult;
/**
* Integration test for {@link MongoTemplate}.
*
*
* @author Oliver Gierke
* @author Thomas Risberg
*/

View File

@@ -5,15 +5,19 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.document.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.document.mongodb.convert.MappingMongoConverter;
import com.mongodb.Mongo;
public class TestMongoConfiguration extends AbstractMongoConfiguration {
@Override
public String defaultDatabaseName() {
return "database";
}
@Bean
public Mongo mongo() throws Exception {
return new Mongo("localhost", 27017);
@@ -21,24 +25,21 @@ public class TestMongoConfiguration extends AbstractMongoConfiguration {
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), "database", mappingMongoConverter());
return new MongoTemplate(mongoDbFactory());
}
@Override
public String getMappingBasePackage() {
public String mappingBasePackage() {
return "org.springframework.data.document.mongodb.mapping";
}
@Override
protected void afterMappingMongoConverterCreation(
MappingMongoConverter converter) {
super.afterMappingMongoConverterCreation(converter);
protected void afterMappingMongoConverterCreation(MappingMongoConverter converter) {
Set<Converter<?, ?>> converterList = new HashSet<Converter<?, ?>>();
converterList.add(new org.springframework.data.document.mongodb.PersonReadConverter());
converterList.add(new org.springframework.data.document.mongodb.PersonWriteConverter());
converter.setCustomConverters(converterList);
}
}

View File

@@ -20,6 +20,8 @@ import static org.mockito.Mockito.*;
import java.util.Arrays;
import java.util.HashSet;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Before;
@@ -30,17 +32,13 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.annotation.Id;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoMappingContext;
import org.springframework.data.document.mongodb.mapping.MongoPersistentEntity;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
/**
* Test case to verify correct usage of custom {@link Converter} implementations to be used.
*
* @see DATADOC-101
*
* @author Oliver Gierke
* @see DATADOC-101
*/
@RunWith(MockitoJUnitRunner.class)
public class CustomConvertersUnitTests {

View File

@@ -2,8 +2,6 @@ package org.springframework.data.document.mongodb.mapping;
import com.mongodb.Mongo;
import org.springframework.context.annotation.Bean;
import org.springframework.data.document.mongodb.MongoDbFactory;
import org.springframework.data.document.mongodb.MongoDbFactoryBean;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.config.AbstractMongoConfiguration;
@@ -12,19 +10,19 @@ public class GeoIndexedAppConfig extends AbstractMongoConfiguration {
public static String GEO_DB = "geodb";
public static String GEO_COLLECTION = "geolocation";
@Override
public String defaultDatabaseName() {
return GEO_DB;
}
@Bean
public Mongo mongo() throws Exception {
return new Mongo("localhost");
}
@Bean
public MongoDbFactory mongoDbFactory() throws Exception {
return new MongoDbFactoryBean(mongo(), GEO_DB);
}
@Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory(), mappingMongoConverter());
return new MongoTemplate(mongoDbFactory());
}
public String getMappingBasePackage() {

View File

@@ -78,7 +78,7 @@ public class MappingTests {
}
applicationContext = new ClassPathXmlApplicationContext("/mapping.xml");
template = applicationContext.getBean(MongoTemplate.class);
mappingContext = applicationContext.getBean(MongoMappingContext.class);
mappingContext = (MongoMappingContext) template.getMappingContext();
}
@Test

View File

@@ -1,23 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<property name="host" value="localhost"/>
<property name="port" value="27017"/>
</bean>
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<property name="host" value="localhost"/>
<property name="port" value="27017"/>
</bean>
<bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.MongoDbFactoryBean">
<constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="database"/>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<constructor-arg name="mongoConverter" ref="mongoConverter" />
</bean>
<bean id="mongoConverter" class="org.springframework.data.document.mongodb.convert.SimpleMongoConverter" />
<bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.MongoDbFactoryBean">
<constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="database"/>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
</bean>
</beans>

View File

@@ -1,18 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
<mongo:db-factory db="database"/>
<mongo:mapping-converter id="mappingConverter" base-package="org.springframework.data.document.mongodb.mapping"/>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg>
<mongo:db-factory db="database"/>
</constructor-arg>
</bean>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/>
<constructor-arg name="mongoConverter" ref="mappingConverter"/>
</bean>
<bean class="org.springframework.data.document.mongodb.mapping.event.LoggingEventListener"/>
<bean class="org.springframework.data.document.mongodb.mapping.event.LoggingEventListener"/>
</beans>

View File

@@ -7,13 +7,8 @@
<bean class="org.springframework.data.document.mongodb.TestMongoConfiguration"/>
<mongo:db-factory/>
<mongo:db-factory db="database"/>
<bean id="mongoDbFactory" class="org.springframework.data.document.mongodb.MongoDbFactoryBean">
<constructor-arg name="mongo" ref="mongo"/>
<constructor-arg name="databaseName" value="database"/>
</bean>
<bean id="mappingConverter1" class="org.springframework.data.document.mongodb.convert.MappingMongoConverter">
<constructor-arg ref="mappingContext" />
<property name="customConverters">