DATADOC-119 added support for registering custom converters with the mongo namespace support
This commit is contained in:
@@ -16,15 +16,21 @@
|
||||
|
||||
package org.springframework.data.document.mongodb.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
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.BeanDefinitionHolder;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
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.ManagedList;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.ManagedSet;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
@@ -37,6 +43,7 @@ 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.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
@@ -101,6 +108,19 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
registry.registerBeanDefinition(INDEX_HELPER, indexHelperBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
List<Element> customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters");
|
||||
if (customConvertersElements.size() == 1) {
|
||||
Element customerConvertersElement = customConvertersElements.get(0);
|
||||
ManagedList converterBeans = new ManagedList();
|
||||
List<Element> listenerElements = DomUtils.getChildElementsByTagName(customerConvertersElement, "converter");
|
||||
if (listenerElements != null) {
|
||||
for (Element listenerElement : listenerElements) {
|
||||
converterBeans.add(parseConverter(listenerElement, parserContext));
|
||||
}
|
||||
}
|
||||
converterBuilder.addPropertyValue("converters", converterBeans);
|
||||
}
|
||||
|
||||
return converterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
@@ -124,4 +144,24 @@ public class MappingMongoConverterParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
public BeanDefinition parseConverter(Element element, ParserContext parserContext) {
|
||||
|
||||
String converterRef= element.getAttribute("ref");
|
||||
if (StringUtils.hasText(converterRef)) {
|
||||
//TODO: need to make this work for beans not in the registry yet
|
||||
BeanDefinition converterBean = parserContext.getRegistry().getBeanDefinition(converterRef);
|
||||
return converterBean;
|
||||
}
|
||||
Element beanElement = DomUtils.getChildElementByTagName(element, "bean");
|
||||
if (beanElement != null) {
|
||||
BeanDefinitionHolder beanDef = parserContext.getDelegate().parseBeanDefinitionElement(beanElement);
|
||||
beanDef = parserContext.getDelegate().decorateBeanDefinitionIfRequired(beanElement, beanDef);
|
||||
return beanDef.getBeanDefinition();
|
||||
}
|
||||
|
||||
parserContext.getReaderContext().error(
|
||||
"Element <converter> must specify either 'ref' or contain a bean definition for the converter", element);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/data/mongo"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
targetNamespace="http://www.springframework.org/schema/data/mongo"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context"
|
||||
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd"/>
|
||||
@@ -126,6 +132,22 @@ Defines a MongoConverter for getting rich mapping functionality.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="custom-converters" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Top-level element that contains one or more custom converters to be used for mapping
|
||||
domain objects to and from Mongo's DBObject
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="converter" type="customConverterType" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -260,5 +282,30 @@ This controls whether or not on a connect, the system retries automatically. De
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:group name="beanElementGroup">
|
||||
<xsd:choice>
|
||||
<xsd:element ref="beans:bean" />
|
||||
<xsd:element ref="beans:ref" />
|
||||
</xsd:choice>
|
||||
</xsd:group>
|
||||
|
||||
<xsd:complexType name="customConverterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Element defining a custom converterr.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:group ref="beanElementGroup" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:attribute name="ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
A reference to a custom converter.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref" />
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* 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;
|
||||
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.document.mongodb.convert.MongoConverter;
|
||||
import org.springframework.data.document.mongodb.query.Criteria;
|
||||
import org.springframework.data.document.mongodb.query.Query;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBObject;
|
||||
import com.mongodb.MongoException;
|
||||
|
||||
/**
|
||||
* Integration test for {@link MongoTemplate}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Risberg
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("classpath:template-mapping.xml")
|
||||
public class MongoTemplateMappingTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoTemplate1")
|
||||
MongoTemplate template1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("mongoTemplate2")
|
||||
MongoTemplate template2;
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
template1.dropCollection(template1.getCollectionName(Person.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertsEntityCorrectly1() throws Exception {
|
||||
|
||||
addAndRetrievePerson(template1);
|
||||
checkPersonPersisted(template1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertsEntityCorrectly2() throws Exception {
|
||||
|
||||
addAndRetrievePerson(template2);
|
||||
checkPersonPersisted(template2);
|
||||
|
||||
}
|
||||
|
||||
private void addAndRetrievePerson(MongoTemplate template) {
|
||||
Person person = new Person("Oliver");
|
||||
person.setAge(25);
|
||||
template.insert(person);
|
||||
|
||||
List<Person> result = template.find(new Query(Criteria.where("_id").is(person.getId())), Person.class);
|
||||
assertThat(result.size(), is(1));
|
||||
assertThat(result, hasItem(person));
|
||||
assertThat(result.get(0).getFirstName(), is("Oliver"));
|
||||
assertThat(result.get(0).getAge(), is(25));
|
||||
}
|
||||
|
||||
private void checkPersonPersisted(MongoTemplate template) {
|
||||
template.execute(Person.class, new CollectionCallback<Object>() {
|
||||
public Object doInCollection(DBCollection collection)
|
||||
throws MongoException, DataAccessException {
|
||||
DBObject dbo = collection.findOne();
|
||||
assertThat((String)dbo.get("name"), is("Oliver"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.springframework.data.document.mongodb;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
public class PersonReadConverter implements Converter<DBObject, Person> {
|
||||
|
||||
public Person convert(DBObject source) {
|
||||
Person p = new Person((ObjectId)source.get("_id"), (String)source.get("name"));
|
||||
p.setAge((Integer) source.get("age"));
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.springframework.data.document.mongodb;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
public class PersonWriteConverter implements Converter<Person, DBObject> {
|
||||
|
||||
public DBObject convert(Person source) {
|
||||
DBObject dbo = new BasicDBObject();
|
||||
dbo.put("_id", source.getId());
|
||||
dbo.put("name", source.getFirstName());
|
||||
dbo.put("age", source.getAge());
|
||||
return dbo;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,5 +12,21 @@
|
||||
|
||||
<mongo:mongo id="defaultMongo" host="localhost" port="27017"/>
|
||||
|
||||
<bean id="readConverter" class="org.springframework.data.document.mongodb.PersonReadConverter"/>
|
||||
|
||||
<mongo:mapping-converter>
|
||||
<mongo:custom-converters>
|
||||
<mongo:converter ref="readConverter"/>
|
||||
<mongo:converter>
|
||||
<bean class="org.springframework.data.document.mongodb.PersonWriteConverter"/>
|
||||
</mongo:converter>
|
||||
</mongo:custom-converters>
|
||||
</mongo:mapping-converter>
|
||||
|
||||
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
|
||||
<constructor-arg name="mongo" ref="mongo"/>
|
||||
<constructor-arg name="databaseName" value="database"/>
|
||||
<constructor-arg name="mongoConverter" ref="mappingConverter"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
|
||||
47
spring-data-mongodb/src/test/resources/template-mapping.xml
Normal file
47
spring-data-mongodb/src/test/resources/template-mapping.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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
|
||||
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd">
|
||||
|
||||
<mongo:mongo host="localhost" port="27017"/>
|
||||
|
||||
<bean id="mappingConverter1" class="org.springframework.data.document.mongodb.convert.MappingMongoConverter">
|
||||
<constructor-arg ref="mappingContext" />
|
||||
<property name="converters">
|
||||
<list>
|
||||
<bean class="org.springframework.data.document.mongodb.PersonReadConverter"/>
|
||||
<bean class="org.springframework.data.document.mongodb.PersonWriteConverter"/>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="mappingContext" class="org.springframework.data.document.mongodb.mapping.MongoMappingContext"/>
|
||||
|
||||
<bean id="mongoTemplate1" class="org.springframework.data.document.mongodb.MongoTemplate">
|
||||
<constructor-arg ref="mongo"/>
|
||||
<constructor-arg name="databaseName" value="database"/>
|
||||
<constructor-arg ref="mappingConverter1"/>
|
||||
</bean>
|
||||
|
||||
<mongo:mapping-converter id="mappingConverter2" base-package="org.springframework.data.document.mongodb.mapping"
|
||||
mongo-template-ref="mongoTemplate2">
|
||||
<mongo:custom-converters>
|
||||
<mongo:converter>
|
||||
<bean class="org.springframework.data.document.mongodb.PersonReadConverter"/>
|
||||
</mongo:converter>
|
||||
<mongo:converter>
|
||||
<bean class="org.springframework.data.document.mongodb.PersonWriteConverter"/>
|
||||
</mongo:converter>
|
||||
</mongo:custom-converters>
|
||||
</mongo:mapping-converter>
|
||||
|
||||
<bean id="mongoTemplate2" class="org.springframework.data.document.mongodb.MongoTemplate">
|
||||
<constructor-arg ref="mongo"/>
|
||||
<constructor-arg name="databaseName" value="database"/>
|
||||
<constructor-arg ref="mappingConverter2"/>
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user