Properly emit domain events from calls to saveAll(…).
We now treat CrudRepository.saveAll(…) properly by unwrapping the given *Iterable*. This previously already worked for collections handed into the method but not for types only implementing Iterable directly (like Page or Window). Fixes #3153. Related tickets #2931, #2927.
This commit is contained in:
@@ -54,7 +54,15 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
/**
|
||||
* Creates a new {@link EventPublishingRepositoryProxyPostProcessor} for the given {@link ApplicationEventPublisher}.
|
||||
*
|
||||
* @param publisher must not be {@literal null}.
|
||||
*/
|
||||
public EventPublishingRepositoryProxyPostProcessor(ApplicationEventPublisher publisher) {
|
||||
|
||||
Assert.notNull(publisher, "Object must not be null");
|
||||
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@@ -103,9 +111,9 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
return result;
|
||||
}
|
||||
|
||||
Object[] arguments = invocation.getArguments();
|
||||
Iterable<?> arguments = asCollection(invocation.getArguments()[0], invocation.getMethod());
|
||||
|
||||
eventMethod.publishEventsFrom(arguments[0], publisher);
|
||||
eventMethod.publishEventsFrom(arguments, publisher);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -177,22 +185,18 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
/**
|
||||
* Publishes all events in the given aggregate root using the given {@link ApplicationEventPublisher}.
|
||||
*
|
||||
* @param object can be {@literal null}.
|
||||
* @param aggregates can be {@literal null}.
|
||||
* @param publisher must not be {@literal null}.
|
||||
*/
|
||||
public void publishEventsFrom(@Nullable Object object, ApplicationEventPublisher publisher) {
|
||||
public void publishEventsFrom(Iterable<?> aggregates, ApplicationEventPublisher publisher) {
|
||||
|
||||
if (object == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Object aggregateRoot : asCollection(object)) {
|
||||
for (Object aggregateRoot : aggregates) {
|
||||
|
||||
if (!type.isInstance(aggregateRoot)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) {
|
||||
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot), null)) {
|
||||
publisher.publishEvent(event);
|
||||
}
|
||||
|
||||
@@ -261,25 +265,30 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given source object as collection, i.e. collections are returned as is, objects are turned into a
|
||||
* one-element collection, {@literal null} will become an empty collection.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Collection<Object> asCollection(@Nullable Object source) {
|
||||
}
|
||||
|
||||
if (source == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
/**
|
||||
* Returns the given source object as collection, i.e. collections are returned as is, objects are turned into a
|
||||
* one-element collection, {@literal null} will become an empty collection.
|
||||
*
|
||||
* @param source can be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Iterable<Object> asCollection(@Nullable Object source, @Nullable Method method) {
|
||||
|
||||
if (Collection.class.isInstance(source)) {
|
||||
return (Collection<Object>) source;
|
||||
}
|
||||
|
||||
return Collections.singletonList(source);
|
||||
if (source == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (method != null && method.getName().startsWith("saveAll")) {
|
||||
return (Iterable<Object>) source;
|
||||
}
|
||||
|
||||
if (Collection.class.isInstance(source)) {
|
||||
return (Collection<Object>) source;
|
||||
}
|
||||
|
||||
return Collections.singletonList(source);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +64,6 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> EventPublishingMethod.of(null));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-928
|
||||
void publishingEventsForNullIsNoOp() {
|
||||
EventPublishingMethod.of(OneEvent.class).publishEventsFrom(null, publisher);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-928
|
||||
void exposesEventsExposedByEntityToPublisher() {
|
||||
|
||||
@@ -76,7 +71,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
var second = new SomeEvent();
|
||||
var entity = MultipleEvents.of(Arrays.asList(first, second));
|
||||
|
||||
EventPublishingMethod.of(MultipleEvents.class).publishEventsFrom(entity, publisher);
|
||||
EventPublishingMethod.of(MultipleEvents.class).publishEventsFrom(List.of(entity), publisher);
|
||||
|
||||
verify(publisher).publishEvent(eq(first));
|
||||
verify(publisher).publishEvent(eq(second));
|
||||
@@ -88,7 +83,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
var event = new SomeEvent();
|
||||
var entity = OneEvent.of(event);
|
||||
|
||||
EventPublishingMethod.of(OneEvent.class).publishEventsFrom(entity, publisher);
|
||||
EventPublishingMethod.of(OneEvent.class).publishEventsFrom(List.of(entity), publisher);
|
||||
|
||||
verify(publisher, times(1)).publishEvent(event);
|
||||
}
|
||||
@@ -98,7 +93,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
|
||||
var entity = OneEvent.of(null);
|
||||
|
||||
EventPublishingMethod.of(OneEvent.class).publishEventsFrom(entity, publisher);
|
||||
EventPublishingMethod.of(OneEvent.class).publishEventsFrom(List.of(entity), publisher);
|
||||
|
||||
verify(publisher, times(0)).publishEvent(any());
|
||||
}
|
||||
@@ -274,7 +269,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
|
||||
var entity = spy(EventsWithClearing.of(Collections.emptyList()));
|
||||
|
||||
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entity, publisher);
|
||||
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(List.of(entity), publisher);
|
||||
|
||||
verify(entity, times(1)).clearDomainEvents();
|
||||
}
|
||||
@@ -284,7 +279,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
|
||||
var entity = spy(EventsWithClearing.of(Collections.singletonList(new SomeEvent())));
|
||||
|
||||
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(entity, publisher);
|
||||
EventPublishingMethod.of(EventsWithClearing.class).publishEventsFrom(List.of(entity), publisher);
|
||||
|
||||
verify(entity, times(1)).clearDomainEvents();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user