From 417fad340ba7e360c6b838fe8a9e57967b5a95b0 Mon Sep 17 00:00:00 2001 From: yukiyoshida Date: Mon, 15 May 2017 15:44:27 +0900 Subject: [PATCH] DATACMNS-1067 - Fix not to call @AfterDomainEventPublication method from collection of entities. We now make sure the event cleanup method is called on the aggregate root, not on the parameter object directly (as the latter might be a collection. Original pull request: #216. --- ...ublishingRepositoryProxyPostProcessor.java | 10 +++-- ...RepositoryProxyPostProcessorUnitTests.java | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java b/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java index 419a062e6..2cea045a8 100644 --- a/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java +++ b/src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java @@ -44,6 +44,7 @@ import org.springframework.util.ReflectionUtils; * * @author Oliver Gierke * @author Christoph Strobl + * @author Yuki Yoshida * @since 1.13 * @soundtrack Henrik Freischlader Trio - Master Plan (Openness) */ @@ -164,13 +165,14 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr } for (Object aggregateRoot : asCollection(object)) { - for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) { + Collection events = asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot)); + for (Object event : events) { publisher.publishEvent(event); } - } - if (clearingMethod != null) { - ReflectionUtils.invokeMethod(clearingMethod, object); + if (clearingMethod != null && !events.isEmpty()) { + ReflectionUtils.invokeMethod(clearingMethod, aggregateRoot); + } } } diff --git a/src/test/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessorUnitTests.java b/src/test/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessorUnitTests.java index 1f82bd544..2ebbdb5dc 100644 --- a/src/test/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessorUnitTests.java +++ b/src/test/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessorUnitTests.java @@ -20,6 +20,7 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.Value; import java.lang.reflect.Method; @@ -36,6 +37,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.aop.framework.ProxyFactory; import org.springframework.context.ApplicationEventPublisher; +import org.springframework.data.domain.AfterDomainEventPublication; import org.springframework.data.domain.DomainEvents; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.core.RepositoryInformation; @@ -47,6 +49,7 @@ import org.springframework.data.repository.core.support.EventPublishingRepositor * * @author Oliver Gierke * @author Mark Paluch + * @author Yuki Yoshida * @soundtrack Henrik Freischlader Trio - Nobody Else To Blame (Openness) */ @RunWith(MockitoJUnitRunner.class) @@ -99,6 +102,40 @@ public class EventPublishingRepositoryProxyPostProcessorUnitTests { verify(publisher, times(0)).publishEvent(any()); } + @Test // DATACMNS-1067 + public void clearEventsDoesNotExposedByEntity() { + + EventsWithClearing entity = spy(EventsWithClearing.of(Collections.emptyList())); + + EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entity, publisher); + + verify(entity, times(0)).clearDomainEvents(); + } + + @Test // DATACMNS-1067 + public void clearEventsExposedByEntity() { + + EventsWithClearing entity = spy(EventsWithClearing.of(Collections.singletonList(new SomeEvent()))); + + EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entity, publisher); + + verify(entity, times(1)).clearDomainEvents(); + } + + @Test // DATACMNS-1067 + public void clearEventsExposedByEntities() { + + EventsWithClearing firstEntity = spy(EventsWithClearing.of(Collections.emptyList())); + EventsWithClearing secondEntity = spy(EventsWithClearing.of(Collections.singletonList(new SomeEvent()))); + + Collection entities = Arrays.asList(firstEntity, secondEntity); + + EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entities, publisher); + + verify(firstEntity, times(0)).clearDomainEvents(); + verify(secondEntity, times(1)).clearDomainEvents(); + } + @Test // DATACMNS-928 public void doesNotCreatePublishingMethodIfNoAnnotationDetected() { assertThat(EventPublishingMethod.of(Object.class)).isNull(); @@ -210,6 +247,14 @@ public class EventPublishingRepositoryProxyPostProcessorUnitTests { @Getter(onMethod = @__(@DomainEvents)) Collection events; } + @RequiredArgsConstructor(staticName = "of") + static class EventsWithClearing { + @Getter(onMethod = @__(@DomainEvents)) final Collection events; + + @AfterDomainEventPublication + void clearDomainEvents() {} + } + @Value(staticConstructor = "of") static class OneEvent { @Getter(onMethod = @__(@DomainEvents)) Object event;