Skip to content

Commit c6f9c40

Browse files
committed
DATACMNS-928 - Refinements for aggregate root domain event publication.
We now publish events for all methods named "save" on the repository. Fundamentally, that's in place to capture calls to CrudRepository.save(Iterable entities), too. Some minor refactorings to the internal setup of EventPublishingMethodInterceptor. More JavaDoc.
1 parent bdf4738 commit c6f9c40

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

src/main/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessor.java

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,18 @@ public void postProcess(ProxyFactory factory, RepositoryInformation repositoryIn
6565
return;
6666
}
6767

68-
factory.addAdvice(new EventPublishingMethodInterceptor(repositoryInformation.getCrudMethods().getSaveMethod(),
69-
method, publisher));
68+
factory.addAdvice(new EventPublishingMethodInterceptor(method, publisher));
7069
}
7170

72-
@RequiredArgsConstructor
71+
/**
72+
* {@link MethodInterceptor} to publish events exposed an aggregate on calls to a save method on the repository.
73+
*
74+
* @author Oliver Gierke
75+
* @since 1.13
76+
*/
77+
@RequiredArgsConstructor(staticName = "of")
7378
static class EventPublishingMethodInterceptor implements MethodInterceptor {
7479

75-
private final Method saveMethod;
7680
private final EventPublishingMethod eventMethod;
7781
private final ApplicationEventPublisher publisher;
7882

@@ -83,7 +87,7 @@ static class EventPublishingMethodInterceptor implements MethodInterceptor {
8387
@Override
8488
public Object invoke(MethodInvocation invocation) throws Throwable {
8589

86-
if (!invocation.getMethod().equals(saveMethod)) {
90+
if (!invocation.getMethod().getName().equals("save")) {
8791
return invocation.proceed();
8892
}
8993

@@ -95,6 +99,12 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
9599
}
96100
}
97101

102+
/**
103+
* Abstraction of a method on the aggregate root that exposes the events to publish.
104+
*
105+
* @author Oliver Gierke
106+
* @since 1.13
107+
*/
98108
@RequiredArgsConstructor
99109
static class EventPublishingMethod {
100110

@@ -151,8 +161,10 @@ public void publishEventsFrom(Object object, ApplicationEventPublisher publisher
151161
return;
152162
}
153163

154-
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, object))) {
155-
publisher.publishEvent(event);
164+
for (Object aggregateRoot : asCollection(object)) {
165+
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) {
166+
publisher.publishEvent(event);
167+
}
156168
}
157169

158170
if (clearingMethod != null) {

src/test/java/org/springframework/data/repository/core/support/EventPublishingRepositoryProxyPostProcessorUnitTests.java

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import lombok.Value;
2626

2727
import java.io.Serializable;
28-
import java.lang.reflect.Method;
2928
import java.util.Arrays;
3029
import java.util.Collection;
3130
import java.util.UUID;
@@ -129,14 +128,14 @@ public void doesNotCreatePublishingMethodIfNoAnnotationDetected() {
129128
@Test
130129
public void interceptsSaveMethod() throws Throwable {
131130

132-
Method saveMethod = SampleRepository.class.getMethod("save", Object.class);
133-
doReturn(saveMethod).when(invocation).getMethod();
131+
doReturn(SampleRepository.class.getMethod("save", Object.class)).when(invocation).getMethod();
134132

135133
SomeEvent event = new SomeEvent();
136134
MultipleEvents sample = MultipleEvents.of(Arrays.asList(event));
137135
doReturn(new Object[] { sample }).when(invocation).getArguments();
138136

139-
new EventPublishingMethodInterceptor(saveMethod, EventPublishingMethod.of(MultipleEvents.class), publisher)
137+
EventPublishingMethodInterceptor//
138+
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
140139
.invoke(invocation);
141140

142141
verify(publisher).publishEvent(event);
@@ -148,10 +147,10 @@ public void interceptsSaveMethod() throws Throwable {
148147
@Test
149148
public void doesNotInterceptNonSaveMethod() throws Throwable {
150149

151-
Method saveMethod = SampleRepository.class.getMethod("save", Object.class);
152150
doReturn(SampleRepository.class.getMethod("findOne", Serializable.class)).when(invocation).getMethod();
153151

154-
new EventPublishingMethodInterceptor(saveMethod, EventPublishingMethod.of(MultipleEvents.class), publisher)
152+
EventPublishingMethodInterceptor//
153+
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
155154
.invoke(invocation);
156155

157156
verify(publisher, never()).publishEvent(any());
@@ -189,6 +188,25 @@ public void doesNotAddAdviceIfDomainTypeDoesNotExposeEvents() {
189188
verify(factory, never()).addAdvice(any(Advice.class));
190189
}
191190

191+
/**
192+
* @see DATACMNS-928
193+
*/
194+
@Test
195+
public void publishesEventsForCallToSaveWithIterable() throws Throwable {
196+
197+
SomeEvent event = new SomeEvent();
198+
MultipleEvents sample = MultipleEvents.of(Arrays.asList(event));
199+
doReturn(new Object[] { Arrays.asList(sample) }).when(invocation).getArguments();
200+
201+
doReturn(SampleRepository.class.getMethod("save", Iterable.class)).when(invocation).getMethod();
202+
203+
EventPublishingMethodInterceptor//
204+
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
205+
.invoke(invocation);
206+
207+
verify(publisher).publishEvent(any(SomeEvent.class));
208+
}
209+
192210
@Value(staticConstructor = "of")
193211
static class MultipleEvents {
194212
@Getter(onMethod = @__(@DomainEvents)) Collection<? extends Object> events;

0 commit comments

Comments
 (0)