From 6540c234130d65891a07d123f1c74dcc0d8bd8f7 Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Thu, 17 Mar 2011 11:57:07 -0500 Subject: [PATCH] Added event handling capabilities based on Spring 2.0 ApplicationEvent abstractions. Publishes events into the current ApplicationContext to expose internal mapping events to listeners declared in the current ApplicationContext. --- .../data/document/mongodb/MongoTemplate.java | 47 ++++++++++++++++-- .../convert/MappingMongoConverter.java | 25 ++++------ .../mongodb/event/CollectionCreatedEvent.java | 42 ++++++++++++++++ .../document/mongodb/event/EventType.java | 27 ++++++++++ .../document/mongodb/event/InsertEvent.java | 42 ++++++++++++++++ .../document/mongodb/event/SaveEvent.java | 42 ++++++++++++++++ .../mongodb/event/WriteResultEvent.java | 35 +++++++++++++ .../mapping/event/MongoMappingEvent.java | 49 +++++++++++++++++++ .../mongodb/mapping/InsertEventListener.java | 43 ++++++++++++++++ .../MappingMongoConverterUnitTests.java | 16 ++++++ .../mongodb/mapping/MappingTests.java | 14 +++++- .../src/test/resources/mapping.xml | 1 + 12 files changed, 362 insertions(+), 21 deletions(-) create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/CollectionCreatedEvent.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/EventType.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/InsertEvent.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/SaveEvent.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/WriteResultEvent.java create mode 100644 spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/event/MongoMappingEvent.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/InsertEventListener.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java index 43054b705..1b9b39acb 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java @@ -22,6 +22,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; +import java.util.concurrent.BlockingDeque; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingDeque; import com.mongodb.BasicDBObject; import com.mongodb.CommandResult; @@ -37,9 +41,13 @@ 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.beans.ConfigurablePropertyAccessor; import org.springframework.beans.PropertyAccessorFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; import org.springframework.core.convert.ConversionFailedException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; @@ -47,6 +55,9 @@ import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoP import org.springframework.data.document.mongodb.convert.MappingMongoConverter; import org.springframework.data.document.mongodb.convert.MongoConverter; 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.query.IndexDefinition; import org.springframework.data.document.mongodb.query.Query; import org.springframework.data.document.mongodb.query.Update; @@ -61,7 +72,7 @@ import org.springframework.util.Assert; * @author Mark Pollack * @author Oliver Gierke */ -public class MongoTemplate implements InitializingBean, MongoOperations { +public class MongoTemplate implements InitializingBean, MongoOperations, ApplicationContextAware { private static final Log LOGGER = LogFactory.getLog(MongoTemplate.class); @@ -87,7 +98,9 @@ public class MongoTemplate implements InitializingBean, MongoOperations { private String databaseName; private String username; private String password; - + private ApplicationContext applicationContext; + private ExecutorService eventPublishers = Executors.newCachedThreadPool(); + private BlockingDeque eventQueue = new LinkedBlockingDeque(); /** * Constructor used for a basic template configuration @@ -173,6 +186,9 @@ public class MongoTemplate implements InitializingBean, MongoOperations { } } + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } /** * Sets the username to use to connect to the Mongo database @@ -548,6 +564,9 @@ public class MongoTemplate implements InitializingBean, MongoOperations { writer.write(objectToSave, dbDoc); Object id = insertDBObject(collectionName, dbDoc); populateIdIfNecessary(objectToSave, id); + if (null != applicationContext) { + eventQueue.add(new InsertEvent(collectionName, dbDoc)); + } } /* (non-Javadoc) @@ -621,6 +640,9 @@ public class MongoTemplate implements InitializingBean, MongoOperations { writer.write(objectToSave, dbDoc); ObjectId id = saveDBObject(collectionName, dbDoc); populateIdIfNecessary(objectToSave, id); + if (null != applicationContext) { + eventQueue.add(new SaveEvent(collectionName, dbDoc)); + } } @@ -806,7 +828,11 @@ public class MongoTemplate implements InitializingBean, MongoOperations { protected DBCollection doCreateCollection(final String collectionName, final DBObject collectionOptions) { return execute(new DbCallback() { public DBCollection doInDB(DB db) throws MongoException, DataAccessException { - return db.createCollection(collectionName, collectionOptions); + DBCollection coll = db.createCollection(collectionName, collectionOptions); + if (null != applicationContext) { + eventQueue.add(new CollectionCreatedEvent(collectionName, collectionOptions)); + } + return coll; } }); } @@ -1043,6 +1069,21 @@ public class MongoTemplate implements InitializingBean, MongoOperations { ((MappingMongoConverter) mongoConverter).setMongo(mongo); ((MappingMongoConverter) mongoConverter).setDefaultDatabase(databaseName); } + if (null != applicationContext) { + eventPublishers.submit(new Runnable() { + public void run() { + while (true) { + ApplicationEvent event = null; + try { + event = eventQueue.take(); + applicationContext.publishEvent(event); + } catch (InterruptedException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + }); + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java index 886fbdf5d..000531d95 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java @@ -64,13 +64,14 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; /** * {@link MongoConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to * {@link DBObject}. - * + * * @author Jon Brisbin * @author Oliver Gierke */ public class MappingMongoConverter implements MongoConverter, ApplicationContextAware { private static final String CUSTOM_TYPE_KEY = "_class"; + @SuppressWarnings({"unchecked"}) private static final List> MONGO_TYPES = Arrays.asList(Number.class, Date.class, String.class, DBObject.class); protected static final Log log = LogFactory.getLog(MappingMongoConverter.class); @@ -107,7 +108,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext /** * 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(Converter converter) { @@ -352,13 +353,6 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext entity.doWithProperties(new PropertyHandler() { public void doWithPersistentProperty(PersistentProperty prop) { String name = prop.getName(); - if (null != idProperty && name.equals(idProperty.getName())) { - return; - } - if (prop.isAssociation()) { - return; - } - Class type = prop.getType(); Object propertyObj = null; try { @@ -406,9 +400,9 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext * configured {@link ConversionService} to {@link MappingBeanHelper}. */ protected void initializeConverters() { - + this.conversionService.removeConvertible(Object.class, String.class); - + if (!conversionService.canConvert(ObjectId.class, String.class)) { conversionService.addConverter(ObjectIdToStringConverter.INSTANCE); conversionService.addConverter(StringToObjectIdConverter.INSTANCE); @@ -417,7 +411,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext conversionService.addConverter(ObjectIdToBigIntegerConverter.INSTANCE); conversionService.addConverter(BigIntegerToIdConverter.INSTANCE); } - + MappingBeanHelper.setConversionService(conversionService); } @@ -425,11 +419,10 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext protected void writePropertyInternal(PersistentProperty prop, Object obj, DBObject dbo) { org.springframework.data.document.mongodb.mapping.DBRef dbref = prop.getField() .getAnnotation(org.springframework.data.document.mongodb.mapping.DBRef.class); - + String name = prop.getName(); - + Class type = prop.getType(); if (prop.isCollection()) { - Class type = prop.getType(); BasicDBList dbList = new BasicDBList(); Collection coll = (type.isArray() ? Arrays.asList((Object[]) obj) : (Collection) obj); for (Object propObjItem : coll) { @@ -472,7 +465,7 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext BasicDBObject propDbObj = new BasicDBObject(); write(obj, propDbObj, mappingContext.getPersistentEntity(prop.getTypeInformation())); dbo.put(name, propDbObj); - + } protected void writeMapInternal(Map obj, DBObject dbo) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/CollectionCreatedEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/CollectionCreatedEvent.java new file mode 100644 index 000000000..a07356fc8 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/CollectionCreatedEvent.java @@ -0,0 +1,42 @@ +/* + * 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.event; + +import com.mongodb.DBObject; +import org.springframework.context.ApplicationEvent; + +/** + * @author Jon Brisbin + */ +public class CollectionCreatedEvent extends ApplicationEvent { + + private final DBObject options; + + public CollectionCreatedEvent(String collection, DBObject options) { + super(collection); + this.options = options; + } + + public String getCollection() { + return (String) super.getSource(); + } + + public DBObject getOptions() { + return options; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/EventType.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/EventType.java new file mode 100644 index 000000000..3cb5336ce --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/EventType.java @@ -0,0 +1,27 @@ +/* + * 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.event; + +/** + * @author Jon Brisbin + */ +public enum EventType { + COLLECTION_CREATED, + DOCUMENT_INSERTED, + DOCUMENT_UPDATED, + DOCUMENT_DELETED +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/InsertEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/InsertEvent.java new file mode 100644 index 000000000..94121ff05 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/InsertEvent.java @@ -0,0 +1,42 @@ +/* + * 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.event; + +import com.mongodb.DBObject; +import org.springframework.context.ApplicationEvent; + +/** + * @author Jon Brisbin + */ +public class InsertEvent extends ApplicationEvent { + + private final String collection; + + public InsertEvent(String collection, DBObject dbo) { + super(dbo); + this.collection = collection; + } + + public String getCollection() { + return collection; + } + + public DBObject getDBObject() { + return (DBObject) source; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/SaveEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/SaveEvent.java new file mode 100644 index 000000000..c9e40b765 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/SaveEvent.java @@ -0,0 +1,42 @@ +/* + * 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.event; + +import com.mongodb.DBObject; +import org.springframework.context.ApplicationEvent; + +/** + * @author Jon Brisbin + */ +public class SaveEvent extends ApplicationEvent { + + private final String collection; + + public SaveEvent(String collection, DBObject source) { + super(source); + this.collection = collection; + } + + public DBObject getDBObject() { + return (DBObject) source; + } + + public String getCollection() { + return collection; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/WriteResultEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/WriteResultEvent.java new file mode 100644 index 000000000..bfbedc9c7 --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/event/WriteResultEvent.java @@ -0,0 +1,35 @@ +/* + * 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.event; + +import com.mongodb.WriteResult; +import org.springframework.context.ApplicationEvent; + +/** + * @author Jon Brisbin + */ +public class WriteResultEvent extends ApplicationEvent { + + public WriteResultEvent(WriteResult result) { + super(result); + } + + public WriteResult getWriteResult() { + return (WriteResult) source; + } + +} diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/event/MongoMappingEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/event/MongoMappingEvent.java new file mode 100644 index 000000000..f422a651c --- /dev/null +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/mapping/event/MongoMappingEvent.java @@ -0,0 +1,49 @@ +/* + * 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 org.springframework.context.ApplicationEvent; +import org.springframework.data.document.mongodb.event.EventType; +import org.springframework.data.mapping.model.PersistentEntity; + +/** + * @author Jon Brisbin + */ +public class MongoMappingEvent extends ApplicationEvent { + + private final EventType type; + private final PersistentEntity entity; + + public MongoMappingEvent(EventType type, PersistentEntity entity, T target) { + super(target); + this.type = type; + this.entity = entity; + } + + public EventType getType() { + return type; + } + + public PersistentEntity getEntity() { + return entity; + } + + @Override + public T getSource() { + return (T) super.getSource(); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/InsertEventListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/InsertEventListener.java new file mode 100644 index 000000000..0e7f4a3ce --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/InsertEventListener.java @@ -0,0 +1,43 @@ +/* + * 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; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.data.document.mongodb.event.InsertEvent; + +/** + * @author Jon Brisbin + */ +public class InsertEventListener implements ApplicationListener { + + private Logger log = LoggerFactory.getLogger(getClass()); + private AtomicInteger counter = new AtomicInteger(0); + + public void onApplicationEvent(InsertEvent event) { + log.info("Got INSERT event: " + event); + counter.incrementAndGet(); + } + + public int getCount() { + return counter.get(); + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java index b8bcb460b..29f534393 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingMongoConverterUnitTests.java @@ -1,3 +1,19 @@ +/* + * 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; import static org.hamcrest.Matchers.*; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java index d87d043e5..b342afa90 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java @@ -16,8 +16,7 @@ package org.springframework.data.document.mongodb.mapping; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import java.util.ArrayList; @@ -30,6 +29,7 @@ import com.mongodb.DBObject; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.data.document.mongodb.MongoTemplate; import org.springframework.data.document.mongodb.convert.MappingMongoConverter; import org.springframework.data.document.mongodb.query.Criteria; @@ -45,12 +45,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @ContextConfiguration("classpath:mapping.xml") public class MappingTests { + @Autowired + ApplicationContext applicationContext; @Autowired MongoTemplate template; @Autowired BasicMappingContext mappingContext; @Autowired MappingMongoConverter mongoConverter; + @Autowired + InsertEventListener insertEventListener; @Test public void setUp() { @@ -144,6 +148,11 @@ public class MappingTests { assertNotNull(p.getId()); } + @Test + public void testEventHandling() { + assertThat(insertEventListener.getCount(), greaterThan(0)); + } + @Test public void testReadEntity() { List result = template.find(new Query(Criteria.where("ssn").is(123456789)), Person.class); @@ -151,4 +160,5 @@ public class MappingTests { assertThat(result.get(0).getAddress().getCountry(), is("USA")); assertThat(result.get(0).getAccounts(), notNullValue()); } + } diff --git a/spring-data-mongodb/src/test/resources/mapping.xml b/spring-data-mongodb/src/test/resources/mapping.xml index 010431b54..65ee2cfed 100644 --- a/spring-data-mongodb/src/test/resources/mapping.xml +++ b/spring-data-mongodb/src/test/resources/mapping.xml @@ -30,4 +30,5 @@ +