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 e517c69dc..90200607d 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 @@ -65,14 +65,18 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr return; } - factory.addAdvice(new EventPublishingMethodInterceptor(repositoryInformation.getCrudMethods().getSaveMethod(), - method, publisher)); + factory.addAdvice(new EventPublishingMethodInterceptor(method, publisher)); } - @RequiredArgsConstructor + /** + * {@link MethodInterceptor} to publish events exposed an aggregate on calls to a save method on the repository. + * + * @author Oliver Gierke + * @since 1.13 + */ + @RequiredArgsConstructor(staticName = "of") static class EventPublishingMethodInterceptor implements MethodInterceptor { - private final Method saveMethod; private final EventPublishingMethod eventMethod; private final ApplicationEventPublisher publisher; @@ -83,7 +87,7 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr @Override public Object invoke(MethodInvocation invocation) throws Throwable { - if (!invocation.getMethod().equals(saveMethod)) { + if (!invocation.getMethod().getName().equals("save")) { return invocation.proceed(); } @@ -95,6 +99,12 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr } } + /** + * Abstraction of a method on the aggregate root that exposes the events to publish. + * + * @author Oliver Gierke + * @since 1.13 + */ @RequiredArgsConstructor static class EventPublishingMethod { @@ -151,8 +161,10 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr return; } - for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, object))) { - publisher.publishEvent(event); + for (Object aggregateRoot : asCollection(object)) { + for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) { + publisher.publishEvent(event); + } } if (clearingMethod != null) { 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 8030d4028..a4953a65b 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 @@ -25,7 +25,6 @@ import lombok.Getter; import lombok.Value; import java.io.Serializable; -import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.UUID; @@ -129,14 +128,14 @@ public class EventPublishingRepositoryProxyPostProcessorUnitTests { @Test public void interceptsSaveMethod() throws Throwable { - Method saveMethod = SampleRepository.class.getMethod("save", Object.class); - doReturn(saveMethod).when(invocation).getMethod(); + doReturn(SampleRepository.class.getMethod("save", Object.class)).when(invocation).getMethod(); SomeEvent event = new SomeEvent(); MultipleEvents sample = MultipleEvents.of(Arrays.asList(event)); doReturn(new Object[] { sample }).when(invocation).getArguments(); - new EventPublishingMethodInterceptor(saveMethod, EventPublishingMethod.of(MultipleEvents.class), publisher) + EventPublishingMethodInterceptor// + .of(EventPublishingMethod.of(MultipleEvents.class), publisher)// .invoke(invocation); verify(publisher).publishEvent(event); @@ -148,10 +147,10 @@ public class EventPublishingRepositoryProxyPostProcessorUnitTests { @Test public void doesNotInterceptNonSaveMethod() throws Throwable { - Method saveMethod = SampleRepository.class.getMethod("save", Object.class); doReturn(SampleRepository.class.getMethod("findOne", Serializable.class)).when(invocation).getMethod(); - new EventPublishingMethodInterceptor(saveMethod, EventPublishingMethod.of(MultipleEvents.class), publisher) + EventPublishingMethodInterceptor// + .of(EventPublishingMethod.of(MultipleEvents.class), publisher)// .invoke(invocation); verify(publisher, never()).publishEvent(any()); @@ -189,6 +188,25 @@ public class EventPublishingRepositoryProxyPostProcessorUnitTests { verify(factory, never()).addAdvice(any(Advice.class)); } + /** + * @see DATACMNS-928 + */ + @Test + public void publishesEventsForCallToSaveWithIterable() throws Throwable { + + SomeEvent event = new SomeEvent(); + MultipleEvents sample = MultipleEvents.of(Arrays.asList(event)); + doReturn(new Object[] { Arrays.asList(sample) }).when(invocation).getArguments(); + + doReturn(SampleRepository.class.getMethod("save", Iterable.class)).when(invocation).getMethod(); + + EventPublishingMethodInterceptor// + .of(EventPublishingMethod.of(MultipleEvents.class), publisher)// + .invoke(invocation); + + verify(publisher).publishEvent(any(SomeEvent.class)); + } + @Value(staticConstructor = "of") static class MultipleEvents { @Getter(onMethod = @__(@DomainEvents)) Collection events;