diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java index 619b2a277..c7d787297 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java @@ -1486,7 +1486,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware { public T doWith(DBObject object) { if (null != object) { - maybeEmitEvent(new AfterLoadEvent(object)); + maybeEmitEvent(new AfterLoadEvent(object, type)); } T source = reader.read(type, object); if (null != source) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java index 13d8380fa..69595d612 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java @@ -43,29 +43,35 @@ public abstract class AbstractMongoEventListener implements ApplicationListen * (non-Javadoc) * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) */ - @SuppressWarnings("unchecked") public void onApplicationEvent(MongoMappingEvent event) { - - Object source = event.getSource(); - + // Invoke domain type independent events if (event instanceof AfterLoadEvent) { - onAfterLoad(((AfterLoadEvent) event).getSource()); + AfterLoadEvent afterLoadEvent = (AfterLoadEvent) event; + + if (domainClass.isAssignableFrom(afterLoadEvent.getType())) { + onAfterLoad(event.getDBObject()); + } + + return; } - + + @SuppressWarnings("unchecked") + E source = (E) event.getSource(); + // Check for matching domain type and invoke callbacks if (source != null && !domainClass.isAssignableFrom(source.getClass())) { return; } if (event instanceof BeforeConvertEvent) { - onBeforeConvert((E) source); + onBeforeConvert(source); } else if (event instanceof BeforeSaveEvent) { - onBeforeSave((E) source, event.getDBObject()); + onBeforeSave(source, event.getDBObject()); } else if (event instanceof AfterSaveEvent) { - onAfterSave((E) source, event.getDBObject()); + onAfterSave(source, event.getDBObject()); } else if (event instanceof AfterConvertEvent) { - onAfterConvert(event.getDBObject(), (E) source); + onAfterConvert(event.getDBObject(), source); } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java index 8e4c38abc..bdb5ad774 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java @@ -16,16 +16,42 @@ package org.springframework.data.mongodb.core.mapping.event; +import org.springframework.util.Assert; + import com.mongodb.DBObject; /** - * @author Jon Brisbin + * Event to be triggered after loading {@link DBObject}s to be mapped onto a given type. + * + * @author Oliver Gierke + * @author Jon Brisbin + * @author Christoph Leiter */ -public class AfterLoadEvent extends MongoMappingEvent { +public class AfterLoadEvent extends MongoMappingEvent { private static final long serialVersionUID = 1L; + private final Class type; + + /** + * Creates a new {@link AfterLoadEvent} for the given {@link DBObject} and type. + * + * @param dbo must not be {@literal null}. + * @param type must not be {@literal null}. + */ + public AfterLoadEvent(DBObject dbo, Class type) { + + super(dbo, dbo); + + Assert.notNull(type, "Type must not be null!"); + this.type = type; + } - public AfterLoadEvent(DBObject dbo) { - super(dbo, null); + /** + * Returns the type for which the {@link AfterLoadEvent} shall be invoked for. + * + * @return + */ + public Class getType() { + return type; } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTest.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTest.java index 87d9953ff..1c54cc842 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTest.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTest.java @@ -17,8 +17,11 @@ package org.springframework.data.mongodb.core.mapping.event; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; + import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.data.mongodb.core.mapping.Account; +import org.springframework.data.mongodb.repository.Contact; import org.springframework.data.mongodb.repository.Person; import com.mongodb.BasicDBObject; @@ -35,7 +38,7 @@ public class AbstractMongoEventListenerUnitTest { public void invokesCallbackForEventForPerson() { MongoMappingEvent event = new BeforeConvertEvent(new Person("Dave", "Matthews")); - SampleEventListener listener = new SampleEventListener(); + SamplePersonEventListener listener = new SamplePersonEventListener(); listener.onApplicationEvent(event); assertThat(listener.invokedOnBeforeConvert, is(true)); } @@ -45,8 +48,8 @@ public class AbstractMongoEventListenerUnitTest { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); context.refresh(); - - SampleEventListener listener = new SampleEventListener(); + + SamplePersonEventListener listener = new SamplePersonEventListener(); context.addApplicationListener(listener); context.publishEvent(new BeforeConvertEvent(new Person("Dave", "Matthews"))); @@ -62,15 +65,59 @@ public class AbstractMongoEventListenerUnitTest { */ @Test public void afterLoadEffectGetsHandledCorrectly() { - - SampleEventListener listener = new SampleEventListener(); - listener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject())); + + SamplePersonEventListener listener = new SamplePersonEventListener(); + listener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Person.class)); assertThat(listener.invokedOnAfterLoad, is(true)); } - - class SampleEventListener extends AbstractMongoEventListener { - + /** + * @see DATADOC-289 + */ + @Test + public void afterLoadEventGetsFilteredForDomainType() { + + SamplePersonEventListener personListener = new SamplePersonEventListener(); + SampleAccountEventListener accountListener = new SampleAccountEventListener(); + personListener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Person.class)); + accountListener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Person.class)); + + assertThat(personListener.invokedOnAfterLoad, is(true)); + assertThat(accountListener.invokedOnAfterLoad, is(false)); + } + + /** + * @see DATADOC-289 + */ + @Test + public void afterLoadEventGetsFilteredForDomainTypeWorksForSubtypes() { + + SamplePersonEventListener personListener = new SamplePersonEventListener(); + SampleContactEventListener contactListener = new SampleContactEventListener(); + personListener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Person.class)); + contactListener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Person.class)); + + assertThat(personListener.invokedOnAfterLoad, is(true)); + assertThat(contactListener.invokedOnAfterLoad, is(true)); + } + + /** + * @see DATADOC-289 + */ + @Test + public void afterLoadEventGetsFilteredForDomainTypeWorksForSubtypes2() { + + SamplePersonEventListener personListener = new SamplePersonEventListener(); + SampleContactEventListener contactListener = new SampleContactEventListener(); + personListener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Contact.class)); + contactListener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject(), Contact.class)); + + assertThat(personListener.invokedOnAfterLoad, is(false)); + assertThat(contactListener.invokedOnAfterLoad, is(true)); + } + + class SamplePersonEventListener extends AbstractMongoEventListener { + boolean invokedOnBeforeConvert; boolean invokedOnAfterLoad; @@ -84,4 +131,36 @@ public class AbstractMongoEventListenerUnitTest { invokedOnAfterLoad = true; } } + + class SampleContactEventListener extends AbstractMongoEventListener { + + boolean invokedOnBeforeConvert; + boolean invokedOnAfterLoad; + + @Override + public void onBeforeConvert(Contact source) { + invokedOnBeforeConvert = true; + } + + @Override + public void onAfterLoad(DBObject dbo) { + invokedOnAfterLoad = true; + } + } + + class SampleAccountEventListener extends AbstractMongoEventListener { + + boolean invokedOnBeforeConvert; + boolean invokedOnAfterLoad; + + @Override + public void onBeforeConvert(Account source) { + invokedOnBeforeConvert = true; + } + + @Override + public void onAfterLoad(DBObject dbo) { + invokedOnAfterLoad = true; + } + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java index b433ff375..b1850e5e6 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java @@ -20,12 +20,12 @@ import java.util.ArrayList; import com.mongodb.DBObject; -public class SimpleMappingEventListener extends AbstractMongoEventListener { +public class SimpleMappingEventListener extends AbstractMongoEventListener { public final ArrayList> onBeforeConvertEvents = new ArrayList>(); public final ArrayList> onBeforeSaveEvents = new ArrayList>(); public final ArrayList> onAfterSaveEvents = new ArrayList>(); - public final ArrayList onAfterLoadEvents = new ArrayList(); + public final ArrayList> onAfterLoadEvents = new ArrayList>(); public final ArrayList> onAfterConvertEvents = new ArrayList>(); @Override @@ -45,7 +45,7 @@ public class SimpleMappingEventListener extends AbstractMongoEventListener(dbo, Object.class)); } @Override