diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MappingMongoConverterParser.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MappingMongoConverterParser.java index 2e0f6ddfe..158691df8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MappingMongoConverterParser.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/config/MappingMongoConverterParser.java @@ -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 customConvertersElements = DomUtils.getChildElementsByTagName(element, "custom-converters"); + if (customConvertersElements.size() == 1) { + Element customerConvertersElement = customConvertersElements.get(0); + ManagedList converterBeans = new ManagedList(); + List 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 must specify either 'ref' or contain a bean definition for the converter", element); + return null; + } } diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd index 5bc020070..e89ee3d88 100644 --- a/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/document/mongodb/config/spring-mongo-1.0.xsd @@ -1,12 +1,18 @@ + elementFormDefault="qualified" attributeFormDefault="unqualified" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + + @@ -126,6 +132,22 @@ Defines a MongoConverter for getting rich mapping functionality. ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A reference to a custom converter. + + + + + + + \ No newline at end of file diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateMappingTests.java new file mode 100644 index 000000000..1f3721441 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/MongoTemplateMappingTests.java @@ -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 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() { + public Object doInCollection(DBCollection collection) + throws MongoException, DataAccessException { + DBObject dbo = collection.findOne(); + assertThat((String)dbo.get("name"), is("Oliver")); + return null; + } + }); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/PersonReadConverter.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/PersonReadConverter.java new file mode 100644 index 000000000..235fce457 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/PersonReadConverter.java @@ -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 { + + 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; + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/PersonWriteConverter.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/PersonWriteConverter.java new file mode 100644 index 000000000..d91d0948d --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/PersonWriteConverter.java @@ -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 { + + 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; + } + +} diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/config/MongoNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/config/MongoNamespaceTests-context.xml index 31c3f3a91..724afafef 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/config/MongoNamespaceTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/document/mongodb/config/MongoNamespaceTests-context.xml @@ -12,5 +12,21 @@ + + + + + + + + + + + + + + + + diff --git a/spring-data-mongodb/src/test/resources/template-mapping.xml b/spring-data-mongodb/src/test/resources/template-mapping.xml new file mode 100644 index 000000000..1b803f37d --- /dev/null +++ b/spring-data-mongodb/src/test/resources/template-mapping.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +