Skip to content

Commit 7fc1526

Browse files
sis-yoshidayodrotbohm
authored andcommitted
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.
1 parent 8a4656d commit 7fc1526

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

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

+7-4
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
* will be invoked after all events have been published.
4545
*
4646
* @author Oliver Gierke
47+
* @author Christoph Strobl
48+
* @author Yuki Yoshida
4749
* @since 1.13
4850
* @soundtrack Henrik Freischlader Trio - Master Plan (Openness)
4951
*/
@@ -164,13 +166,14 @@ public void publishEventsFrom(Object object, ApplicationEventPublisher publisher
164166
}
165167

166168
for (Object aggregateRoot : asCollection(object)) {
167-
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) {
169+
Collection<Object> events = asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot));
170+
for (Object event : events) {
168171
publisher.publishEvent(event);
169172
}
170-
}
171173

172-
if (clearingMethod != null) {
173-
ReflectionUtils.invokeMethod(clearingMethod, object);
174+
if (clearingMethod != null && !events.isEmpty()) {
175+
ReflectionUtils.invokeMethod(clearingMethod, aggregateRoot);
176+
}
174177
}
175178
}
176179

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

+46
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import static org.mockito.Mockito.*;
2323

2424
import lombok.Getter;
25+
import lombok.RequiredArgsConstructor;
2526
import lombok.Value;
2627

2728
import java.io.Serializable;
@@ -39,6 +40,7 @@
3940
import org.mockito.runners.MockitoJUnitRunner;
4041
import org.springframework.aop.framework.ProxyFactory;
4142
import org.springframework.context.ApplicationEventPublisher;
43+
import org.springframework.data.domain.AfterDomainEventPublication;
4244
import org.springframework.data.domain.DomainEvents;
4345
import org.springframework.data.repository.CrudRepository;
4446
import org.springframework.data.repository.core.RepositoryInformation;
@@ -49,6 +51,8 @@
4951
* Unit tests for {@link EventPublishingRepositoryProxyPostProcessor} and contained classes.
5052
*
5153
* @author Oliver Gierke
54+
* @author Mark Paluch
55+
* @author Yuki Yoshida
5256
* @soundtrack Henrik Freischlader Trio - Nobody Else To Blame (Openness)
5357
*/
5458
@RunWith(MockitoJUnitRunner.class)
@@ -101,6 +105,40 @@ public void doesNotExposeNullEvent() {
101105
verify(publisher, times(0)).publishEvent(any());
102106
}
103107

108+
@Test // DATACMNS-1067
109+
public void clearEventsDoesNotExposedByEntity() {
110+
111+
EventsWithClearing entity = spy(EventsWithClearing.of(Collections.emptyList()));
112+
113+
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entity, publisher);
114+
115+
verify(entity, times(0)).clearDomainEvents();
116+
}
117+
118+
@Test // DATACMNS-1067
119+
public void clearEventsExposedByEntity() {
120+
121+
EventsWithClearing entity = spy(EventsWithClearing.of(Collections.singletonList(new SomeEvent())));
122+
123+
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entity, publisher);
124+
125+
verify(entity, times(1)).clearDomainEvents();
126+
}
127+
128+
@Test // DATACMNS-1067
129+
public void clearEventsExposedByEntities() {
130+
131+
EventsWithClearing firstEntity = spy(EventsWithClearing.of(Collections.emptyList()));
132+
EventsWithClearing secondEntity = spy(EventsWithClearing.of(Collections.singletonList(new SomeEvent())));
133+
134+
Collection<EventsWithClearing> entities = Arrays.asList(firstEntity, secondEntity);
135+
136+
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entities, publisher);
137+
138+
verify(firstEntity, times(0)).clearDomainEvents();
139+
verify(secondEntity, times(1)).clearDomainEvents();
140+
}
141+
104142
@Test // DATACMNS-928
105143
public void doesNotCreatePublishingMethodIfNoAnnotationDetected() {
106144
assertThat(EventPublishingMethod.of(Object.class), is(nullValue()));
@@ -215,6 +253,14 @@ static class MultipleEvents {
215253
@Getter(onMethod = @__(@DomainEvents)) Collection<? extends Object> events;
216254
}
217255

256+
@RequiredArgsConstructor(staticName = "of")
257+
static class EventsWithClearing {
258+
@Getter(onMethod = @__(@DomainEvents)) final Collection<? extends Object> events;
259+
260+
@AfterDomainEventPublication
261+
void clearDomainEvents() {}
262+
}
263+
218264
@Value(staticConstructor = "of")
219265
static class OneEvent {
220266
@Getter(onMethod = @__(@DomainEvents)) Object event;

0 commit comments

Comments
 (0)