DATAMONGO-545 - Add BeforeDeleteEvent and AfterDeleteEvent.
Added events for before and after deletion of documents. Polished logging code in AbstractMongoEventListener.
This commit is contained in:
committed by
Oliver Gierke
parent
0eb315a758
commit
8b50af07ce
@@ -68,9 +68,11 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoSimpleTypes;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterConvertEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterDeleteEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterLoadEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeDeleteEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent;
|
||||
import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent;
|
||||
import org.springframework.data.mongodb.core.mapreduce.GroupBy;
|
||||
@@ -1031,6 +1033,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
execute(collectionName, new CollectionCallback<Void>() {
|
||||
public Void doInCollection(DBCollection collection) throws MongoException, DataAccessException {
|
||||
|
||||
maybeEmitEvent(new BeforeDeleteEvent<T>(queryObject, entityClass));
|
||||
|
||||
DBObject dboq = mapper.getMappedObject(queryObject, entity);
|
||||
|
||||
MongoAction mongoAction = new MongoAction(writeConcern, MongoActionOperation.REMOVE, collectionName,
|
||||
@@ -1044,6 +1048,9 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
WriteResult wr = writeConcernToUse == null ? collection.remove(dboq) : collection.remove(dboq,
|
||||
writeConcernToUse);
|
||||
handleAnyWriteResultErrors(wr, dboq, MongoActionOperation.REMOVE);
|
||||
|
||||
maybeEmitEvent(new AfterDeleteEvent<T>(queryObject, entityClass));
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2013 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.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Base class for delete events.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
*/
|
||||
public abstract class AbstractDeleteEvent<T> extends MongoMappingEvent<DBObject> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Class<T> type;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type , possibly be {@literal null}.
|
||||
*/
|
||||
public AbstractDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
|
||||
super(dbo, dbo);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type for which the {@link AbstractDeleteEvent} shall be invoked for.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 by the original author(s).
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -27,6 +27,7 @@ import com.mongodb.DBObject;
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Oliver Gierke
|
||||
* @author Martin Baumgartner
|
||||
*/
|
||||
public abstract class AbstractMongoEventListener<E> implements ApplicationListener<MongoMappingEvent<?>> {
|
||||
|
||||
@@ -45,6 +46,7 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void onApplicationEvent(MongoMappingEvent<?> event) {
|
||||
|
||||
if (event instanceof AfterLoadEvent) {
|
||||
@@ -57,6 +59,22 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
return;
|
||||
}
|
||||
|
||||
if (event instanceof AbstractDeleteEvent) {
|
||||
|
||||
Class<?> eventDomainType = ((AbstractDeleteEvent) event).getType();
|
||||
|
||||
if (eventDomainType != null && domainClass.isAssignableFrom(eventDomainType)) {
|
||||
if (event instanceof BeforeDeleteEvent) {
|
||||
onBeforeDelete(event.getDBObject());
|
||||
}
|
||||
if (event instanceof AfterDeleteEvent) {
|
||||
onAfterDelete(event.getDBObject());
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
E source = (E) event.getSource();
|
||||
|
||||
@@ -78,31 +96,43 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
|
||||
|
||||
public void onBeforeConvert(E source) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeConvert(" + source + ")");
|
||||
LOG.debug("onBeforeConvert({})", source);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBeforeSave(E source, DBObject dbo) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onBeforeSave(" + source + ", " + dbo + ")");
|
||||
LOG.debug("onBeforeSave({}, {})", source, dbo);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAfterSave(E source, DBObject dbo) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterSave(" + source + ", " + dbo + ")");
|
||||
LOG.debug("onAfterSave({}, {})", source, dbo);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterLoad(" + dbo + ")");
|
||||
LOG.debug("onAfterLoad({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAfterConvert(DBObject dbo, E source) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterConvert(" + dbo + "," + source + ")");
|
||||
LOG.debug("onAfterConvert({}, {})", dbo, source);
|
||||
}
|
||||
}
|
||||
|
||||
public void onAfterDelete(DBObject dbo) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterConvert({})", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBeforeDelete(DBObject dbo) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("onAfterConvert({})", dbo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2013 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.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Event being thrown after a single or a set of documents has/have been deleted. The {@link DBObject} held in the event
|
||||
* will be the query document <em>after</am> it has been mapped onto the domain type handled.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
*/
|
||||
public class AfterDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AfterDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
*/
|
||||
public AfterDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
super(dbo, type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2013 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.mongodb.core.mapping.event;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* Event being thrown before a document is deleted. The {@link DBObject} held in the event will represent the query
|
||||
* document <em>before</em> being mapped based on the domain class handled.
|
||||
*
|
||||
* @author Martin Baumgartner
|
||||
*/
|
||||
public class BeforeDeleteEvent<T> extends AbstractDeleteEvent<T> {
|
||||
|
||||
private static final long serialVersionUID = -2627547705679734497L;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BeforeDeleteEvent} for the given {@link DBObject} and type.
|
||||
*
|
||||
* @param dbo must not be {@literal null}.
|
||||
* @param type can be {@literal null}.
|
||||
*/
|
||||
public BeforeDeleteEvent(DBObject dbo, Class<T> type) {
|
||||
super(dbo, type);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011-2012 the original author or authors.
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -17,15 +17,19 @@ package org.springframework.data.mongodb.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jbrisbin@vmware.com>
|
||||
* {@link ApplicationListener} for Mongo mapping events logging the events.
|
||||
*
|
||||
* @author Jon Brisbin
|
||||
* @author Martin Baumgartner
|
||||
*/
|
||||
public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LoggingEventListener.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingEventListener.class);
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
@@ -33,7 +37,7 @@ public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeConvert(Object source) {
|
||||
log.info("onBeforeConvert: " + source);
|
||||
LOGGER.info("onBeforeConvert: {}", source);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -42,10 +46,7 @@ public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeSave(Object source, DBObject dbo) {
|
||||
try {
|
||||
log.info("onBeforeSave: " + source + ", " + dbo);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
LOGGER.info("onBeforeSave: {}, {}", source, dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -54,7 +55,7 @@ public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
*/
|
||||
@Override
|
||||
public void onAfterSave(Object source, DBObject dbo) {
|
||||
log.info("onAfterSave: " + source + ", " + dbo);
|
||||
LOGGER.info("onAfterSave: {}, {}", source, dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -63,7 +64,7 @@ public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
*/
|
||||
@Override
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
log.info("onAfterLoad: " + dbo);
|
||||
LOGGER.info("onAfterLoad: {}", dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -72,6 +73,24 @@ public class LoggingEventListener extends AbstractMongoEventListener<Object> {
|
||||
*/
|
||||
@Override
|
||||
public void onAfterConvert(DBObject dbo, Object source) {
|
||||
log.info("onAfterConvert: " + dbo + ", " + source);
|
||||
LOGGER.info("onAfterConvert: {}, {}", dbo, source);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onAfterDelete(com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onAfterDelete(DBObject dbo) {
|
||||
LOGGER.info("onAfterDelete: {}", dbo);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener#onBeforeDelete(com.mongodb.DBObject)
|
||||
*/
|
||||
@Override
|
||||
public void onBeforeDelete(DBObject dbo) {
|
||||
LOGGER.info("onBeforeDelete: {}", dbo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2011 by the original author(s).
|
||||
* Copyright 2011-2013 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.
|
||||
@@ -31,6 +31,7 @@ import com.mongodb.DBObject;
|
||||
* Unit tests for {@link AbstractMongoEventListener}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Martin Baumgartner
|
||||
*/
|
||||
public class AbstractMongoEventListenerUnitTests {
|
||||
|
||||
@@ -61,7 +62,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATADOC-289
|
||||
* @see DATAMONGO-289
|
||||
*/
|
||||
@Test
|
||||
public void afterLoadEffectGetsHandledCorrectly() {
|
||||
@@ -72,7 +73,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATADOC-289
|
||||
* @see DATAMONGO-289
|
||||
*/
|
||||
@Test
|
||||
public void afterLoadEventGetsFilteredForDomainType() {
|
||||
@@ -87,7 +88,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATADOC-289
|
||||
* @see DATAMONGO-289
|
||||
*/
|
||||
@Test
|
||||
public void afterLoadEventGetsFilteredForDomainTypeWorksForSubtypes() {
|
||||
@@ -102,7 +103,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATADOC-289
|
||||
* @see DATAMONGO-289
|
||||
*/
|
||||
@Test
|
||||
public void afterLoadEventGetsFilteredForDomainTypeWorksForSubtypes2() {
|
||||
@@ -117,7 +118,7 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATADOC-333
|
||||
* @see DATAMONGO-333
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@@ -127,10 +128,64 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
listener.onApplicationEvent(new MongoMappingEvent(new Object(), new BasicDBObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-545
|
||||
*/
|
||||
@Test
|
||||
public void invokeContactCallbackForPersonEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class);
|
||||
SampleContactEventListener listener = new SampleContactEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
assertThat(listener.invokedOnBeforeDelete, is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-545
|
||||
*/
|
||||
@Test
|
||||
public void invokePersonCallbackForPersonEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Person>(new BasicDBObject(), Person.class);
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
assertThat(listener.invokedOnBeforeDelete, is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-545
|
||||
*/
|
||||
@Test
|
||||
public void dontInvokePersonCallbackForAccountEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), Account.class);
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
assertThat(listener.invokedOnBeforeDelete, is(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-545
|
||||
*/
|
||||
@Test
|
||||
public void donInvokePersonCallbackForUntypedEvent() {
|
||||
|
||||
MongoMappingEvent<DBObject> event = new BeforeDeleteEvent<Account>(new BasicDBObject(), null);
|
||||
SamplePersonEventListener listener = new SamplePersonEventListener();
|
||||
listener.onApplicationEvent(event);
|
||||
|
||||
assertThat(listener.invokedOnBeforeDelete, is(false));
|
||||
}
|
||||
|
||||
class SamplePersonEventListener extends AbstractMongoEventListener<Person> {
|
||||
|
||||
boolean invokedOnBeforeConvert;
|
||||
boolean invokedOnAfterLoad;
|
||||
boolean invokedOnBeforeDelete;
|
||||
boolean invokedOnAfterDelete;
|
||||
|
||||
@Override
|
||||
public void onBeforeConvert(Person source) {
|
||||
@@ -141,12 +196,24 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
invokedOnAfterLoad = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterDelete(DBObject dbo) {
|
||||
invokedOnAfterDelete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeDelete(DBObject dbo) {
|
||||
invokedOnBeforeDelete = true;
|
||||
}
|
||||
}
|
||||
|
||||
class SampleContactEventListener extends AbstractMongoEventListener<Contact> {
|
||||
|
||||
boolean invokedOnBeforeConvert;
|
||||
boolean invokedOnAfterLoad;
|
||||
boolean invokedOnBeforeDelete;
|
||||
boolean invokedOnAfterDelete;
|
||||
|
||||
@Override
|
||||
public void onBeforeConvert(Contact source) {
|
||||
@@ -157,6 +224,17 @@ public class AbstractMongoEventListenerUnitTests {
|
||||
public void onAfterLoad(DBObject dbo) {
|
||||
invokedOnAfterLoad = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterDelete(DBObject dbo) {
|
||||
invokedOnAfterDelete = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBeforeDelete(DBObject dbo) {
|
||||
invokedOnBeforeDelete = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SampleAccountEventListener extends AbstractMongoEventListener<Account> {
|
||||
|
||||
Reference in New Issue
Block a user