Publish delete events by repository methods deleteInBatch and deleteAllInBatch methods.
We now publish events from deleteInBatch and deleteAllInBatch methods to consider well-known repository methods. We also now prevent event publication if the method argument is not an instance of the domain type. Closes: #2448.
This commit is contained in:
@@ -129,7 +129,8 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
}
|
||||
|
||||
private static boolean isDeleteMethod(String methodName) {
|
||||
return methodName.equals("delete") || methodName.equals("deleteAll");
|
||||
return methodName.equals("delete") || methodName.equals("deleteAll") || methodName.equals("deleteInBatch")
|
||||
|| methodName.equals("deleteAllInBatch");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,13 +142,16 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
static class EventPublishingMethod {
|
||||
|
||||
private static Map<Class<?>, EventPublishingMethod> cache = new ConcurrentReferenceHashMap<>();
|
||||
private static @SuppressWarnings("null") EventPublishingMethod NONE = new EventPublishingMethod(null, null);
|
||||
private static @SuppressWarnings("null") EventPublishingMethod NONE = new EventPublishingMethod(Object.class, null,
|
||||
null);
|
||||
|
||||
private final Class<?> type;
|
||||
private final Method publishingMethod;
|
||||
private final @Nullable Method clearingMethod;
|
||||
|
||||
EventPublishingMethod(Method publishingMethod, Method clearingMethod) {
|
||||
EventPublishingMethod(Class<?> type, Method publishingMethod, @Nullable Method clearingMethod) {
|
||||
|
||||
this.type = type;
|
||||
this.publishingMethod = publishingMethod;
|
||||
this.clearingMethod = clearingMethod;
|
||||
}
|
||||
@@ -170,7 +174,7 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
return eventPublishingMethod.orNull();
|
||||
}
|
||||
|
||||
EventPublishingMethod result = from(getDetector(type, DomainEvents.class),
|
||||
EventPublishingMethod result = from(type, getDetector(type, DomainEvents.class),
|
||||
() -> getDetector(type, AfterDomainEventPublication.class));
|
||||
|
||||
cache.put(type, result);
|
||||
@@ -192,6 +196,10 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
|
||||
for (Object aggregateRoot : asCollection(object)) {
|
||||
|
||||
if (!type.isInstance(aggregateRoot)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) {
|
||||
publisher.publishEvent(event);
|
||||
}
|
||||
@@ -229,7 +237,7 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
* @param clearing must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static EventPublishingMethod from(AnnotationDetectionMethodCallback<?> publishing,
|
||||
private static EventPublishingMethod from(Class<?> type, AnnotationDetectionMethodCallback<?> publishing,
|
||||
Supplier<AnnotationDetectionMethodCallback<?>> clearing) {
|
||||
|
||||
if (!publishing.hasFoundAnnotation()) {
|
||||
@@ -239,7 +247,7 @@ public class EventPublishingRepositoryProxyPostProcessor implements RepositoryPr
|
||||
Method eventMethod = publishing.getRequiredMethod();
|
||||
ReflectionUtils.makeAccessible(eventMethod);
|
||||
|
||||
return new EventPublishingMethod(eventMethod, getClearingMethod(clearing.get()));
|
||||
return new EventPublishingMethod(type, eventMethod, getClearingMethod(clearing.get()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -127,7 +127,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1663
|
||||
public void interceptsDeleteMethod() throws Throwable {
|
||||
void interceptsDeleteMethod() throws Throwable {
|
||||
SomeEvent event = new SomeEvent();
|
||||
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
|
||||
mockInvocation(invocation, SampleRepository.class.getMethod("delete", Object.class), sample);
|
||||
@@ -152,7 +152,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1663
|
||||
public void doesNotInterceptDeleteByIdMethod() throws Throwable {
|
||||
void doesNotInterceptDeleteByIdMethod() throws Throwable {
|
||||
|
||||
doReturn(SampleRepository.class.getMethod("deleteById", Object.class)).when(invocation).getMethod();
|
||||
|
||||
@@ -204,7 +204,7 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1663
|
||||
public void publishesEventsForCallToDeleteWithIterable() throws Throwable {
|
||||
void publishesEventsForCallToDeleteWithIterable() throws Throwable {
|
||||
|
||||
SomeEvent event = new SomeEvent();
|
||||
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
|
||||
@@ -217,6 +217,34 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
verify(publisher).publishEvent(any(SomeEvent.class));
|
||||
}
|
||||
|
||||
@Test // GH-2448
|
||||
void publishesEventsForCallToDeleteInBatchWithIterable() throws Throwable {
|
||||
|
||||
SomeEvent event = new SomeEvent();
|
||||
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
|
||||
mockInvocation(invocation, SampleRepository.class.getMethod("deleteInBatch", Iterable.class), sample);
|
||||
|
||||
EventPublishingMethodInterceptor//
|
||||
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
|
||||
.invoke(invocation);
|
||||
|
||||
verify(publisher).publishEvent(any(SomeEvent.class));
|
||||
}
|
||||
|
||||
@Test // GH-2448
|
||||
void publishesEventsForCallToDeleteAllInBatchWithIterable() throws Throwable {
|
||||
|
||||
SomeEvent event = new SomeEvent();
|
||||
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
|
||||
mockInvocation(invocation, SampleRepository.class.getMethod("deleteAllInBatch", Iterable.class), sample);
|
||||
|
||||
EventPublishingMethodInterceptor//
|
||||
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
|
||||
.invoke(invocation);
|
||||
|
||||
verify(publisher).publishEvent(any(SomeEvent.class));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-975
|
||||
void publishesEventsAfterSaveInvocation() throws Throwable {
|
||||
|
||||
@@ -294,6 +322,17 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
verify(publisher, times(1)).publishEvent(event);
|
||||
}
|
||||
|
||||
@Test // GH-2448
|
||||
void doesNotEmitEventsFromPrimitiveValue() throws Throwable {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("delete", Object.class);
|
||||
mockInvocation(invocation, method, "foo", MultipleEvents.of(Collections.emptySet()));
|
||||
|
||||
EventPublishingMethodInterceptor.of(EventPublishingMethod.of(MultipleEvents.class), publisher).invoke(invocation);
|
||||
|
||||
verify(publisher, never()).publishEvent(any());
|
||||
}
|
||||
|
||||
private static void mockInvocation(MethodInvocation invocation, Method method, Object parameterAndReturnValue)
|
||||
throws Throwable {
|
||||
|
||||
@@ -322,17 +361,23 @@ class EventPublishingRepositoryProxyPostProcessorUnitTests {
|
||||
}
|
||||
|
||||
@Value(staticConstructor = "of")
|
||||
static class OneEvent {
|
||||
private static class OneEvent {
|
||||
@Getter(onMethod = @__(@DomainEvents)) Object event;
|
||||
}
|
||||
|
||||
@Value
|
||||
static class SomeEvent {
|
||||
private static class SomeEvent {
|
||||
UUID id = UUID.randomUUID();
|
||||
}
|
||||
|
||||
interface SampleRepository extends CrudRepository<MultipleEvents, Long> {
|
||||
|
||||
MultipleEvents saveAndFlush(MultipleEvents events);
|
||||
|
||||
MultipleEvents delete(String name);
|
||||
|
||||
MultipleEvents deleteAllInBatch(Iterable<MultipleEvents> events);
|
||||
|
||||
MultipleEvents deleteInBatch(Iterable<MultipleEvents> events);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user