Browse Source

DATADOC-289 - Filter AfterLoadEvent for specific domain type.

AfterLoadEvent can now be typed to a domain type again and will only be invoked if documents are loaded that shall be mapped onto the declared type.
pull/1/head
Christoph Leiter 14 years ago committed by Oliver Gierke
parent
commit
2d12ba38f8
  1. 2
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoTemplate.java
  2. 26
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java
  3. 34
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AfterLoadEvent.java
  4. 97
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListenerUnitTest.java
  5. 6
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/event/SimpleMappingEventListener.java

2
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) { public T doWith(DBObject object) {
if (null != object) { if (null != object) {
maybeEmitEvent(new AfterLoadEvent(object)); maybeEmitEvent(new AfterLoadEvent<T>(object, type));
} }
T source = reader.read(type, object); T source = reader.read(type, object);
if (null != source) { if (null != source) {

26
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/mapping/event/AbstractMongoEventListener.java

@ -43,29 +43,35 @@ public abstract class AbstractMongoEventListener<E> implements ApplicationListen
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/ */
@SuppressWarnings("unchecked")
public void onApplicationEvent(MongoMappingEvent<?> event) { public void onApplicationEvent(MongoMappingEvent<?> event) {
Object source = event.getSource();
// Invoke domain type independent events // Invoke domain type independent events
if (event instanceof AfterLoadEvent) { 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 // Check for matching domain type and invoke callbacks
if (source != null && !domainClass.isAssignableFrom(source.getClass())) { if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
return; return;
} }
if (event instanceof BeforeConvertEvent) { if (event instanceof BeforeConvertEvent) {
onBeforeConvert((E) source); onBeforeConvert(source);
} else if (event instanceof BeforeSaveEvent) { } else if (event instanceof BeforeSaveEvent) {
onBeforeSave((E) source, event.getDBObject()); onBeforeSave(source, event.getDBObject());
} else if (event instanceof AfterSaveEvent) { } else if (event instanceof AfterSaveEvent) {
onAfterSave((E) source, event.getDBObject()); onAfterSave(source, event.getDBObject());
} else if (event instanceof AfterConvertEvent) { } else if (event instanceof AfterConvertEvent) {
onAfterConvert(event.getDBObject(), (E) source); onAfterConvert(event.getDBObject(), source);
} }
} }

34
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; package org.springframework.data.mongodb.core.mapping.event;
import org.springframework.util.Assert;
import com.mongodb.DBObject; import com.mongodb.DBObject;
/** /**
* @author Jon Brisbin <jbrisbin@vmware.com> * 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<DBObject> { public class AfterLoadEvent<T> extends MongoMappingEvent<DBObject> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Class<T> 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<T> 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<T> getType() {
return type;
} }
} }

97
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.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import org.junit.Test; import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext; 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 org.springframework.data.mongodb.repository.Person;
import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObject;
@ -35,7 +38,7 @@ public class AbstractMongoEventListenerUnitTest {
public void invokesCallbackForEventForPerson() { public void invokesCallbackForEventForPerson() {
MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews")); MongoMappingEvent<Person> event = new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"));
SampleEventListener listener = new SampleEventListener(); SamplePersonEventListener listener = new SamplePersonEventListener();
listener.onApplicationEvent(event); listener.onApplicationEvent(event);
assertThat(listener.invokedOnBeforeConvert, is(true)); assertThat(listener.invokedOnBeforeConvert, is(true));
} }
@ -45,8 +48,8 @@ public class AbstractMongoEventListenerUnitTest {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.refresh(); context.refresh();
SampleEventListener listener = new SampleEventListener(); SamplePersonEventListener listener = new SamplePersonEventListener();
context.addApplicationListener(listener); context.addApplicationListener(listener);
context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews"))); context.publishEvent(new BeforeConvertEvent<Person>(new Person("Dave", "Matthews")));
@ -62,15 +65,59 @@ public class AbstractMongoEventListenerUnitTest {
*/ */
@Test @Test
public void afterLoadEffectGetsHandledCorrectly() { public void afterLoadEffectGetsHandledCorrectly() {
SampleEventListener listener = new SampleEventListener(); SamplePersonEventListener listener = new SamplePersonEventListener();
listener.onApplicationEvent(new AfterLoadEvent(new BasicDBObject())); listener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
assertThat(listener.invokedOnAfterLoad, is(true)); assertThat(listener.invokedOnAfterLoad, is(true));
} }
class SampleEventListener extends AbstractMongoEventListener<Person> { /**
* @see DATADOC-289
*/
@Test
public void afterLoadEventGetsFilteredForDomainType() {
SamplePersonEventListener personListener = new SamplePersonEventListener();
SampleAccountEventListener accountListener = new SampleAccountEventListener();
personListener.onApplicationEvent(new AfterLoadEvent<Person>(new BasicDBObject(), Person.class));
accountListener.onApplicationEvent(new AfterLoadEvent<Person>(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<Person>(new BasicDBObject(), Person.class));
contactListener.onApplicationEvent(new AfterLoadEvent<Person>(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<Contact>(new BasicDBObject(), Contact.class));
contactListener.onApplicationEvent(new AfterLoadEvent<Contact>(new BasicDBObject(), Contact.class));
assertThat(personListener.invokedOnAfterLoad, is(false));
assertThat(contactListener.invokedOnAfterLoad, is(true));
}
class SamplePersonEventListener extends AbstractMongoEventListener<Person> {
boolean invokedOnBeforeConvert; boolean invokedOnBeforeConvert;
boolean invokedOnAfterLoad; boolean invokedOnAfterLoad;
@ -84,4 +131,36 @@ public class AbstractMongoEventListenerUnitTest {
invokedOnAfterLoad = true; invokedOnAfterLoad = true;
} }
} }
class SampleContactEventListener extends AbstractMongoEventListener<Contact> {
boolean invokedOnBeforeConvert;
boolean invokedOnAfterLoad;
@Override
public void onBeforeConvert(Contact source) {
invokedOnBeforeConvert = true;
}
@Override
public void onAfterLoad(DBObject dbo) {
invokedOnAfterLoad = true;
}
}
class SampleAccountEventListener extends AbstractMongoEventListener<Account> {
boolean invokedOnBeforeConvert;
boolean invokedOnAfterLoad;
@Override
public void onBeforeConvert(Account source) {
invokedOnBeforeConvert = true;
}
@Override
public void onAfterLoad(DBObject dbo) {
invokedOnAfterLoad = true;
}
}
} }

6
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; import com.mongodb.DBObject;
public class SimpleMappingEventListener extends AbstractMongoEventListener<Object> { public class SimpleMappingEventListener extends AbstractMongoEventListener<Object> {
public final ArrayList<BeforeConvertEvent<Object>> onBeforeConvertEvents = new ArrayList<BeforeConvertEvent<Object>>(); public final ArrayList<BeforeConvertEvent<Object>> onBeforeConvertEvents = new ArrayList<BeforeConvertEvent<Object>>();
public final ArrayList<BeforeSaveEvent<Object>> onBeforeSaveEvents = new ArrayList<BeforeSaveEvent<Object>>(); public final ArrayList<BeforeSaveEvent<Object>> onBeforeSaveEvents = new ArrayList<BeforeSaveEvent<Object>>();
public final ArrayList<AfterSaveEvent<Object>> onAfterSaveEvents = new ArrayList<AfterSaveEvent<Object>>(); public final ArrayList<AfterSaveEvent<Object>> onAfterSaveEvents = new ArrayList<AfterSaveEvent<Object>>();
public final ArrayList<AfterLoadEvent> onAfterLoadEvents = new ArrayList<AfterLoadEvent>(); public final ArrayList<AfterLoadEvent<Object>> onAfterLoadEvents = new ArrayList<AfterLoadEvent<Object>>();
public final ArrayList<AfterConvertEvent<Object>> onAfterConvertEvents = new ArrayList<AfterConvertEvent<Object>>(); public final ArrayList<AfterConvertEvent<Object>> onAfterConvertEvents = new ArrayList<AfterConvertEvent<Object>>();
@Override @Override
@ -45,7 +45,7 @@ public class SimpleMappingEventListener extends AbstractMongoEventListener<Objec
@Override @Override
public void onAfterLoad(DBObject dbo) { public void onAfterLoad(DBObject dbo) {
onAfterLoadEvents.add(new AfterLoadEvent(dbo)); onAfterLoadEvents.add(new AfterLoadEvent<Object>(dbo, Object.class));
} }
@Override @Override

Loading…
Cancel
Save