Added events, changed tests so that application context is created before each run so that indexing is done correctly.

This commit is contained in:
J. Brisbin
2011-03-29 15:05:14 -05:00
parent c6798c9acd
commit 7e5378bf60
12 changed files with 211 additions and 144 deletions

View File

@@ -47,6 +47,8 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
@@ -54,9 +56,12 @@ 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.mapping.event.AfterConvertEvent;
import org.springframework.data.document.mongodb.mapping.event.AfterLoadEvent;
import org.springframework.data.document.mongodb.mapping.event.AfterSaveEvent;
import org.springframework.data.document.mongodb.mapping.event.BeforeConvertEvent;
import org.springframework.data.document.mongodb.mapping.event.BeforeSaveEvent;
import org.springframework.data.document.mongodb.mapping.event.MongoMappingEvent;
import org.springframework.data.document.mongodb.query.IndexDefinition;
import org.springframework.data.document.mongodb.query.Query;
import org.springframework.data.document.mongodb.query.Update;
@@ -71,7 +76,7 @@ import org.springframework.util.Assert;
* @author Mark Pollack
* @author Oliver Gierke
*/
public class MongoTemplate implements InitializingBean, MongoOperations, ApplicationContextAware {
public class MongoTemplate implements InitializingBean, MongoOperations, ApplicationContextAware, ApplicationEventPublisherAware {
private static final Log LOGGER = LogFactory.getLog(MongoTemplate.class);
@@ -98,6 +103,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
private String username;
private String password;
private ApplicationContext applicationContext;
private ApplicationEventPublisher eventPublisher;
private ExecutorService eventPublishers = Executors.newCachedThreadPool();
private LinkedBlockingQueue<ApplicationEvent> eventQueue = new LinkedBlockingQueue<ApplicationEvent>();
@@ -189,6 +195,10 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
this.applicationContext = applicationContext;
}
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
}
/**
* Sets the username to use to connect to the Mongo database
*
@@ -564,12 +574,15 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
*/
public <T> void insert(String collectionName, T objectToSave, MongoWriter<T> writer) {
BasicDBObject dbDoc = new BasicDBObject();
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
writer.write(objectToSave, dbDoc);
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
Object id = insertDBObject(collectionName, dbDoc);
populateIdIfNecessary(objectToSave, id);
if (null != applicationContext) {
eventQueue.add(new InsertEvent(collectionName, dbDoc));
}
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
}
/* (non-Javadoc)
@@ -603,13 +616,19 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
List<DBObject> dbObjectList = new ArrayList<DBObject>();
for (T o : listToSave) {
BasicDBObject dbDoc = new BasicDBObject();
maybeEmitEvent(new BeforeConvertEvent<T>(o));
writer.write(o, dbDoc);
maybeEmitEvent(new BeforeSaveEvent<T>(o, dbDoc));
dbObjectList.add(dbDoc);
}
List<ObjectId> ids = insertDBObjectList(collectionName, dbObjectList);
for (int i = 0; i < listToSave.size(); i++) {
if (i < ids.size()) {
populateIdIfNecessary(listToSave.get(i), ids.get(i));
T obj = listToSave.get(i);
populateIdIfNecessary(obj, ids.get(i));
maybeEmitEvent(new AfterSaveEvent<T>(obj, dbObjectList.get(i)));
}
}
}
@@ -640,12 +659,15 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
*/
public <T> void save(String collectionName, T objectToSave, MongoWriter<T> writer) {
BasicDBObject dbDoc = new BasicDBObject();
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
writer.write(objectToSave, dbDoc);
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
Object id = saveDBObject(collectionName, dbDoc);
populateIdIfNecessary(objectToSave, id);
if (null != applicationContext) {
eventQueue.add(new SaveEvent(collectionName, dbDoc));
}
maybeEmitEvent(new AfterSaveEvent<T>(objectToSave, dbDoc));
}
@@ -821,6 +843,12 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
protected <T> void maybeEmitEvent(MongoMappingEvent<T> event) {
if (null != eventPublisher) {
eventPublisher.publishEvent(event);
}
}
/**
* Create the specified collection using the provided options
*
@@ -832,9 +860,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
return execute(new DbCallback<DBCollection>() {
public DBCollection doInDB(DB db) throws MongoException, DataAccessException {
DBCollection coll = db.createCollection(collectionName, collectionOptions);
if (null != applicationContext) {
eventQueue.add(new CollectionCreatedEvent(collectionName, collectionOptions));
}
// TODO: Emit a collection created event
return coll;
}
});
@@ -1166,7 +1192,7 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
*
* @author Oliver Gierke
*/
private static class ReadDbObjectCallback<T> implements DbObjectCallback<T> {
private class ReadDbObjectCallback<T> implements DbObjectCallback<T> {
private final MongoReader<? super T> reader;
private final Class<T> type;
@@ -1177,7 +1203,10 @@ public class MongoTemplate implements InitializingBean, MongoOperations, Applica
}
public T doWith(DBObject object) {
return reader.read(type, object);
maybeEmitEvent(new AfterLoadEvent<DBObject>(object));
T source = reader.read(type, object);
maybeEmitEvent(new AfterConvertEvent<T>(object, source));
return source;
}
}

View File

@@ -1,43 +0,0 @@
/*
* 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 <jbrisbin@vmware.com>
*/
public class CollectionCreatedEvent extends ApplicationEvent {
private static final long serialVersionUID = -7258679124450904006L;
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;
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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 com.mongodb.DBObject;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public abstract class AbstractMappingEventListener<T extends ApplicationEvent, E> implements ApplicationListener<T> {
@SuppressWarnings({"unchecked"})
public void onApplicationEvent(T appEvent) {
if (appEvent instanceof MongoMappingEvent) {
MongoMappingEvent<E> event = (MongoMappingEvent<E>) appEvent;
if (event instanceof BeforeConvertEvent) {
onBeforeConvert(event.getSource());
} else if (event instanceof BeforeSaveEvent) {
onBeforeSave(event.getSource(), event.getDBObject());
} else if (event instanceof AfterSaveEvent) {
onAfterSave(event.getSource(), event.getDBObject());
} else if (event instanceof AfterLoadEvent) {
onAfterLoad((DBObject) event.getSource());
} else if (event instanceof AfterConvertEvent) {
onAfterConvert(event.getDBObject(), event.getSource());
}
}
}
public void onBeforeConvert(E source) {
}
public void onBeforeSave(E source, DBObject dbo) {
}
public void onAfterSave(E source, DBObject dbo) {
}
public void onAfterLoad(DBObject dbo) {
}
public void onAfterConvert(DBObject dbo, E source) {
}
}

View File

@@ -14,23 +14,19 @@
* limitations under the License.
*/
package org.springframework.data.document.mongodb.event;
package org.springframework.data.document.mongodb.mapping.event;
import com.mongodb.WriteResult;
import org.springframework.context.ApplicationEvent;
import com.mongodb.DBObject;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class WriteResultEvent extends ApplicationEvent {
public class AfterConvertEvent<E> extends MongoMappingEvent<E> {
private static final long serialVersionUID = 4460770341573211038L;
private static final long serialVersionUID = 1L;
public WriteResultEvent(WriteResult result) {
super(result);
public AfterConvertEvent(DBObject dbo, E source) {
super(source, dbo);
}
public WriteResult getWriteResult() {
return (WriteResult) source;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class AfterLoadEvent<DBObject> extends MongoMappingEvent<DBObject> {
private static final long serialVersionUID = 1L;
public AfterLoadEvent(DBObject dbo) {
super(dbo, null);
}
}

View File

@@ -14,30 +14,20 @@
* limitations under the License.
*/
package org.springframework.data.document.mongodb.event;
package org.springframework.data.document.mongodb.mapping.event;
import com.mongodb.DBObject;
import org.springframework.context.ApplicationEvent;
import org.springframework.data.mapping.model.PersistentEntity;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class InsertEvent extends ApplicationEvent {
public class AfterSaveEvent<E> extends MongoMappingEvent<E> {
private static final long serialVersionUID = 8713413423411L;
private final String collection;
private static final long serialVersionUID = 1L;
public InsertEvent(String collection, DBObject dbo) {
super(dbo);
this.collection = collection;
}
public String getCollection() {
return collection;
}
public DBObject getDBObject() {
return (DBObject) source;
public AfterSaveEvent(E source, DBObject dbo) {
super(source, dbo);
}
}

View File

@@ -14,14 +14,17 @@
* limitations under the License.
*/
package org.springframework.data.document.mongodb.event;
package org.springframework.data.document.mongodb.mapping.event;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public enum EventType {
COLLECTION_CREATED,
DOCUMENT_INSERTED,
DOCUMENT_UPDATED,
DOCUMENT_DELETED
public class BeforeConvertEvent<T> extends MongoMappingEvent<T> {
private static final long serialVersionUID = 1L;
public BeforeConvertEvent(T source) {
super(source, null);
}
}

View File

@@ -14,30 +14,19 @@
* limitations under the License.
*/
package org.springframework.data.document.mongodb.event;
package org.springframework.data.document.mongodb.mapping.event;
import com.mongodb.DBObject;
import org.springframework.context.ApplicationEvent;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class SaveEvent extends ApplicationEvent {
public class BeforeSaveEvent<E> extends MongoMappingEvent<E> {
private static final long serialVersionUID = -5583681211168904206L;
private final String collection;
private static final long serialVersionUID = 1L;
public SaveEvent(String collection, DBObject source) {
super(source);
this.collection = collection;
}
public DBObject getDBObject() {
return (DBObject) source;
}
public String getCollection() {
return collection;
public BeforeSaveEvent(E source, DBObject dbo) {
super(source, dbo);
}
}

View File

@@ -16,35 +16,28 @@
package org.springframework.data.document.mongodb.mapping.event;
import com.mongodb.DBObject;
import org.springframework.context.ApplicationEvent;
import org.springframework.data.document.mongodb.event.EventType;
import org.springframework.data.mapping.model.PersistentEntity;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class MongoMappingEvent<T> extends ApplicationEvent {
private static final long serialVersionUID = 1L;
private final EventType type;
private final PersistentEntity<T> entity;
private final DBObject dbo;
public MongoMappingEvent(EventType type, PersistentEntity<T> entity, T target) {
super(target);
this.type = type;
this.entity = entity;
public MongoMappingEvent(T source, DBObject dbo) {
super(source);
this.dbo = dbo;
}
public EventType getType() {
return type;
}
public PersistentEntity<T> getEntity() {
return entity;
public DBObject getDBObject() {
return dbo;
}
@SuppressWarnings({"unchecked"})
@Override
@SuppressWarnings("unchecked")
public T getSource() {
return (T) super.getSource();
}

View File

@@ -16,28 +16,41 @@
package org.springframework.data.document.mongodb.mapping;
import java.util.concurrent.atomic.AtomicInteger;
import com.mongodb.DBObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.data.document.mongodb.event.InsertEvent;
import org.springframework.data.document.mongodb.mapping.event.AbstractMappingEventListener;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
public class InsertEventListener implements ApplicationListener<InsertEvent> {
public class MappingEventsListener<MongoMappingEvent> extends AbstractMappingEventListener {
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();
@Override
public void onBeforeConvert(Object source) {
log.info("onBeforeConvert: " + source);
}
public int getCount() {
return counter.get();
@Override
public void onBeforeSave(Object source, DBObject dbo) {
log.info("onBeforeSave: " + source + ", " + dbo);
}
@Override
public void onAfterSave(Object source, DBObject dbo) {
log.info("onAfterSave: " + source + ", " + dbo);
}
@Override
public void onAfterLoad(DBObject dbo) {
log.info("onAfterLoad: " + dbo);
}
@Override
public void onAfterConvert(DBObject dbo, Object source) {
log.info("onAfterConvert: " + dbo + ", " + source);
}
}

View File

@@ -24,30 +24,30 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.data.document.mongodb.MongoTemplate;
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;
/**
* @author Jon Brisbin <jbrisbin@vmware.com>
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:mapping.xml")
public class MappingTests {
@Autowired
ApplicationContext applicationContext;
@Autowired
MongoTemplate template;
@Autowired
MongoMappingContext mappingContext;
@Before
public void setUp() {
applicationContext = new ClassPathXmlApplicationContext("/mapping.xml");
template = applicationContext.getBean(MongoTemplate.class);
mappingContext = applicationContext.getBean(MongoMappingContext.class);
}
@Test
public void testPersonPojo() {
PersonPojo p = new PersonPojo(12345, "Person", "Pojo");
@@ -144,4 +144,9 @@ public class MappingTests {
assertThat(result.size(), is(1));
}
@Test
public void testEvents(){
}
}

View File

@@ -16,4 +16,6 @@
<constructor-arg ref="mappingConverter"/>
</bean>
<bean class="org.springframework.data.document.mongodb.mapping.MappingEventsListener"/>
</beans>