Added a namespacehandler and broke all the tests. :)

This commit is contained in:
Jon Brisbin
2011-03-17 15:23:24 -05:00
committed by J. Brisbin
parent c4fdc54ffe
commit d215004f92
9 changed files with 186 additions and 70 deletions

View File

@@ -57,6 +57,7 @@ import org.springframework.data.document.mongodb.convert.SimpleMongoConverter;
import org.springframework.data.document.mongodb.event.CollectionCreatedEvent;
import org.springframework.data.document.mongodb.event.InsertEvent;
import org.springframework.data.document.mongodb.event.SaveEvent;
import org.springframework.data.document.mongodb.mapping.MongoMappingConfigurationBuilder;
import org.springframework.data.document.mongodb.query.IndexDefinition;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.document.mongodb.query.Update;
@@ -175,7 +176,6 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
Assert.notNull(mongo);
Assert.notNull(databaseName);
this.mongoConverter = mongoConverter == null ? new SimpleMongoConverter() : mongoConverter;
this.defaultCollectionName = defaultCollectionName;
this.mongo = mongo;
this.databaseName = databaseName;
@@ -183,6 +183,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
if (writeResultChecking != null) {
this.writeResultChecking = writeResultChecking;
}
setMongoConverter(mongoConverter == null ? new SimpleMongoConverter() : mongoConverter);
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
@@ -236,6 +237,10 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return this.mongoConverter;
}
public void setConverter(MongoConverter converter) {
this.mongoConverter = converter;
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoOperations#getDefaultCollectionName()
*/
@@ -1054,20 +1059,23 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return resolved == null ? ex : resolved;
}
private void initializeMappingMongoConverter(MappingMongoConverter converter) {
converter.setMongo(mongo);
converter.setDefaultDatabase(databaseName);
((MongoMappingConfigurationBuilder) converter.getMappingContext().getMappingConfigurationBuilder())
.setMongoTemplate(this);
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() {
if (this.getDefaultCollectionName() != null) {
if (!collectionExists(getDefaultCollectionName())) {
createCollection(getDefaultCollectionName(), null);
}
}
if (null != mongoConverter && mongoConverter instanceof MappingMongoConverter) {
((MappingMongoConverter) mongoConverter).setMongo(mongo);
((MappingMongoConverter) mongoConverter).setDefaultDatabase(databaseName);
}
if (null != applicationContext) {
eventPublishers.submit(new Runnable() {
public void run() {
@@ -1178,6 +1186,9 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
public void setMongoConverter(MongoConverter converter) {
this.mongoConverter = converter;
if (null != converter && converter instanceof MappingMongoConverter) {
initializeMappingMongoConverter((MappingMongoConverter) mongoConverter);
}
}
public void setWriteResultChecking(WriteResultChecking resultChecking) {

View File

@@ -16,12 +16,21 @@
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.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
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.mapping.model.MappingException;
import org.w3c.dom.Element;
/**
@@ -37,17 +46,48 @@ public class MongoMappingConverterParser extends AbstractSingleBeanDefinitionPar
@Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) throws BeanDefinitionStoreException {
String id = super.resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
return "mongoMappingConverter";
}
return id;
return "mappingConverter";
}
@Override
protected Class getBeanClass(Element element) {
return MappingMongoConverter.class;
}
@Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder);
String autowire = element.getAttribute("autowire");
if (null != autowire || !"".equals(autowire)) {
builder.addPropertyValue("autowirePersistentBeans", Boolean.parseBoolean(autowire));
}
// Need a reference to a MongoTemplate
String mongoRef = element.getAttribute("mongo-ref");
if (null == mongoRef || "".equals(mongoRef)) {
mongoRef = "mongo";
}
builder.addPropertyReference("mongo", mongoRef);
// 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<Class<?>> initialEntitySet = new HashSet<Class<?>>(entities.size());
for (BeanDefinition def : entities) {
String clazzName = def.getBeanClassName();
try {
initialEntitySet.add(Class.forName(clazzName));
} catch (ClassNotFoundException e) {
throw new MappingException(e.getMessage(), e);
}
}
builder.addPropertyValue("initialEntitySet", initialEntitySet);
}
}
}
}

View File

@@ -33,9 +33,8 @@ public class MongoRepositoryNamespaceHandler extends NamespaceHandlerSupport {
*/
public void init() {
registerBeanDefinitionParser("repositories",
new MongoRepositoryConfigDefinitionParser());
registerBeanDefinitionParser("repositories", new MongoRepositoryConfigDefinitionParser());
registerBeanDefinitionParser("mapping-converter", new MongoMappingConverterParser());
registerBeanDefinitionParser("mongo", new MongoParser());
registerBeanDefinitionParser("jmx", new MongoJmxParser());
}

View File

@@ -24,9 +24,11 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
@@ -48,7 +50,9 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.document.mongodb.mapping.MongoMappingConfigurationBuilder;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.BasicMappingContext;
import org.springframework.data.mapping.MappingBeanHelper;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.Association;
@@ -68,7 +72,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
* @author Jon Brisbin <jbrisbin@vmware.com>
* @author Oliver Gierke
*/
public class MappingMongoConverter implements MongoConverter, ApplicationContextAware {
public class MappingMongoConverter implements MongoConverter, ApplicationContextAware, InitializingBean {
private static final String CUSTOM_TYPE_KEY = "_class";
@SuppressWarnings({"unchecked"})
@@ -78,12 +82,13 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
protected final GenericConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
protected final Map<Class<?>, Class<?>> customTypeMapping = new HashMap<Class<?>, Class<?>>();
protected SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
protected MappingContext mappingContext;
protected MappingContext mappingContext = new BasicMappingContext(new MongoMappingConfigurationBuilder());
protected ApplicationContext applicationContext;
protected boolean autowirePersistentBeans = false;
protected boolean useFieldAccessOnly = true;
protected Mongo mongo;
protected String defaultDatabase;
protected Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
public MappingMongoConverter() {
initializeConverters();
@@ -124,6 +129,11 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
public void setMappingContext(MappingContext mappingContext) {
this.mappingContext = mappingContext;
if (initialEntitySet.size() > 0 && null == mappingContext.getPersistentEntity(initialEntitySet.iterator().next())) {
for (Class<?> entity : initialEntitySet) {
mappingContext.addPersistentEntity(entity);
}
}
}
public Mongo getMongo() {
@@ -158,6 +168,14 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
this.useFieldAccessOnly = useFieldAccessOnly;
}
public Set<Class<?>> getInitialEntitySet() {
return initialEntitySet;
}
public void setInitialEntitySet(Set<Class<?>> initialEntitySet) {
this.initialEntitySet = initialEntitySet;
}
public <T> T convertObjectId(ObjectId id, Class<T> targetType) {
return conversionService.convert(id, targetType);
}
@@ -600,7 +618,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
* @param dbObject
* @return
*/
private Class<?> findTypeToBeUsed(DBObject dbObject) {
protected Class<?> findTypeToBeUsed(DBObject dbObject) {
Object classToBeUsed = dbObject.get(CUSTOM_TYPE_KEY);
try {
@@ -610,6 +628,12 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext
}
}
public void afterPropertiesSet() throws Exception {
for (Class<?> entity : initialEntitySet) {
//mappingContext.addPersistentEntity(entity);
}
}
/**
* Simple singleton to convert {@link ObjectId}s to their {@link String} representation.
*

View File

@@ -38,7 +38,11 @@ import org.springframework.data.document.mongodb.index.IndexDirection;
import org.springframework.data.document.mongodb.index.Indexed;
import org.springframework.data.mapping.BasicMappingConfigurationBuilder;
import org.springframework.data.mapping.MappingBeanHelper;
import org.springframework.data.mapping.model.*;
import org.springframework.data.mapping.model.Association;
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;
/**
@@ -50,8 +54,15 @@ public class MongoMappingConfigurationBuilder extends BasicMappingConfigurationB
protected Map<String, Indexed> fieldIndexes = new HashMap<String, Indexed>();
protected MongoTemplate mongoTemplate;
public MongoMappingConfigurationBuilder() {
}
public MongoMappingConfigurationBuilder(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
augmentSimpleTypes();
}
protected void augmentSimpleTypes() {
// Augment simpleTypes with MongoDB-specific classes
Set<Class<?>> simpleTypes = MappingBeanHelper.getSimpleTypes();
simpleTypes.add(com.mongodb.DBRef.class);
@@ -59,6 +70,14 @@ public class MongoMappingConfigurationBuilder extends BasicMappingConfigurationB
simpleTypes.add(CodeWScope.class);
}
public MongoTemplate getMongoTemplate() {
return mongoTemplate;
}
public void setMongoTemplate(MongoTemplate mongoTemplate) {
this.mongoTemplate = mongoTemplate;
}
@Override
public PersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, TypeInformation information) throws MappingConfigurationException {
PersistentProperty property = new MongoPersistentProperty(field, descriptor, information);
@@ -130,26 +149,30 @@ public class MongoMappingConfigurationBuilder extends BasicMappingConfigurationB
final boolean unique,
final boolean dropDups,
final boolean sparse) {
mongoTemplate.execute(collection, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
DBObject defObj;
if (null != def) {
defObj = (DBObject) JSON.parse(def);
} else {
defObj = new BasicDBObject();
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
if (null != mongoTemplate) {
mongoTemplate.execute(collection, new CollectionCallback<Object>() {
public Object doInCollection(DBCollection collection) throws MongoException, DataAccessException {
DBObject defObj;
if (null != def) {
defObj = (DBObject) JSON.parse(def);
} else {
defObj = new BasicDBObject();
defObj.put(name, (direction == IndexDirection.ASCENDING ? 1 : -1));
}
DBObject opts = new BasicDBObject();
if (!"".equals(name)) {
opts.put("name", name);
}
opts.put("dropDups", dropDups);
opts.put("sparse", sparse);
opts.put("unique", unique);
collection.ensureIndex(defObj, opts);
return null;
}
DBObject opts = new BasicDBObject();
if (!"".equals(name)) {
opts.put("name", name);
}
opts.put("dropDups", dropDups);
opts.put("sparse", sparse);
opts.put("unique", unique);
collection.ensureIndex(defObj, opts);
return null;
}
});
});
} else {
log.error("MongoTemplate was NULL! Not creating index: " + def + " on collection: " + collection);
}
}
}

View File

@@ -93,6 +93,43 @@ The host to connect to a MongoDB server. Default is localhost
</xsd:complexType>
</xsd:element>
<xsd:element name="mapping-converter">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines a MongoConverter for getting rich mapping functionality.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the MappingMongoConverter instance (by default "mappingConverter").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="base-package" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The base package in which to scan for entities annotated with @Document
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="autowire" type="xsd:boolean">
<xsd:annotation>
<xsd:documentation><![CDATA[
This controls whether or not to run entities through the BeanFactory's autowiring mechanism for using @Autowired and @Value on properties. Default is true.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="mongo-ref" type="mongoRef" use="optional">
<xsd:annotation>
<xsd:documentation>
The reference to a Mongo. Will default to 'mongo'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="jmx">
<xsd:annotation>
<xsd:documentation><![CDATA[

View File

@@ -34,7 +34,6 @@ import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.convert.MappingMongoConverter;
import org.springframework.data.document.mongodb.query.Criteria;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.mapping.BasicMappingContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -50,9 +49,7 @@ public class MappingTests {
@Autowired
MongoTemplate template;
@Autowired
BasicMappingContext mappingContext;
@Autowired
MappingMongoConverter mongoConverter;
MappingMongoConverter mappingConverter;
@Autowired
InsertEventListener insertEventListener;
@@ -66,11 +63,11 @@ public class MappingTests {
public void testConvertSimpleProperty() {
PersonPojo p = new PersonPojo(1234, "Person", "Pojo");
DBObject dbo = new BasicDBObject();
mongoConverter.write(p, dbo);
mappingConverter.write(p, dbo);
assertEquals(dbo.get("ssn"), 1234);
PersonPojo p2 = mongoConverter.read(PersonPojo.class, dbo);
PersonPojo p2 = mappingConverter.read(PersonPojo.class, dbo);
assertEquals(p.getFirstName(), p2.getFirstName());
}

View File

@@ -18,11 +18,9 @@ package org.springframework.data.document.mongodb.mapping;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.annotation.Transient;
import org.springframework.data.document.mongodb.MongoTemplate;
import org.springframework.data.document.mongodb.index.CompoundIndex;
import org.springframework.data.document.mongodb.index.CompoundIndexes;
import org.springframework.data.document.mongodb.index.Indexed;
@@ -49,8 +47,6 @@ public class Person<T extends Address> {
@DBRef
private List<Account> accounts;
private T address;
@Autowired
private MongoTemplate mongoTemplate;
@PersistenceConstructor
public Person(Integer ssn, String firstName, String lastName, Integer age, T address) {

View File

@@ -1,34 +1,23 @@
<?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">
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">
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<property name="host" value="localhost"/>
<property name="port" value="27017"/>
</bean>
<bean id="mappingContext" class="org.springframework.data.mapping.BasicMappingContext">
<property name="mappingConfigurationBuilder">
<bean class="org.springframework.data.document.mongodb.mapping.MongoMappingConfigurationBuilder">
<constructor-arg ref="mongoTemplate"/>
</bean>
</property>
</bean>
<bean id="mongoConverter" class="org.springframework.data.document.mongodb.convert.MappingMongoConverter">
<property name="mappingContext" ref="mappingContext"/>
<property name="autowirePersistentBeans" value="true"/>
</bean>
<mongo:mongo host="localhost" port="27017"/>
<mongo:mapping-converter base-package="org.springframework.data.document.mongodb.mapping"
autowire="true"/>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg ref="mongo"/>
<constructor-arg value="database"/>
<constructor-arg value="person"/>
<constructor-arg ref="mongoConverter"/>
<constructor-arg ref="mappingConverter"/>
</bean>
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator"/>
<bean id="insertEventListener" class="org.springframework.data.document.mongodb.mapping.InsertEventListener"/>
</beans>