Skip to content

Commit 27d4918

Browse files
committed
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.
1 parent dfb6387 commit 27d4918

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ private static boolean isSaveMethod(String methodName) {
129129
}
130130

131131
private static boolean isDeleteMethod(String methodName) {
132-
return methodName.equals("delete") || methodName.equals("deleteAll");
132+
return methodName.equals("delete") || methodName.equals("deleteAll") || methodName.equals("deleteInBatch")
133+
|| methodName.equals("deleteAllInBatch");
133134
}
134135

135136
/**
@@ -141,13 +142,16 @@ private static boolean isDeleteMethod(String methodName) {
141142
static class EventPublishingMethod {
142143

143144
private static Map<Class<?>, EventPublishingMethod> cache = new ConcurrentReferenceHashMap<>();
144-
private static @SuppressWarnings("null") EventPublishingMethod NONE = new EventPublishingMethod(null, null);
145+
private static @SuppressWarnings("null") EventPublishingMethod NONE = new EventPublishingMethod(Object.class, null,
146+
null);
145147

148+
private final Class<?> type;
146149
private final Method publishingMethod;
147150
private final @Nullable Method clearingMethod;
148151

149-
EventPublishingMethod(Method publishingMethod, Method clearingMethod) {
152+
EventPublishingMethod(Class<?> type, Method publishingMethod, @Nullable Method clearingMethod) {
150153

154+
this.type = type;
151155
this.publishingMethod = publishingMethod;
152156
this.clearingMethod = clearingMethod;
153157
}
@@ -170,7 +174,7 @@ public static EventPublishingMethod of(Class<?> type) {
170174
return eventPublishingMethod.orNull();
171175
}
172176

173-
EventPublishingMethod result = from(getDetector(type, DomainEvents.class),
177+
EventPublishingMethod result = from(type, getDetector(type, DomainEvents.class),
174178
() -> getDetector(type, AfterDomainEventPublication.class));
175179

176180
cache.put(type, result);
@@ -192,6 +196,10 @@ public void publishEventsFrom(@Nullable Object object, ApplicationEventPublisher
192196

193197
for (Object aggregateRoot : asCollection(object)) {
194198

199+
if (!type.isInstance(aggregateRoot)) {
200+
continue;
201+
}
202+
195203
for (Object event : asCollection(ReflectionUtils.invokeMethod(publishingMethod, aggregateRoot))) {
196204
publisher.publishEvent(event);
197205
}
@@ -229,7 +237,7 @@ private static <T extends Annotation> AnnotationDetectionMethodCallback<T> getDe
229237
* @param clearing must not be {@literal null}.
230238
* @return
231239
*/
232-
private static EventPublishingMethod from(AnnotationDetectionMethodCallback<?> publishing,
240+
private static EventPublishingMethod from(Class<?> type, AnnotationDetectionMethodCallback<?> publishing,
233241
Supplier<AnnotationDetectionMethodCallback<?>> clearing) {
234242

235243
if (!publishing.hasFoundAnnotation()) {
@@ -239,7 +247,7 @@ private static EventPublishingMethod from(AnnotationDetectionMethodCallback<?> p
239247
Method eventMethod = publishing.getRequiredMethod();
240248
ReflectionUtils.makeAccessible(eventMethod);
241249

242-
return new EventPublishingMethod(eventMethod, getClearingMethod(clearing.get()));
250+
return new EventPublishingMethod(type, eventMethod, getClearingMethod(clearing.get()));
243251
}
244252

245253
/**

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

+50-5
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ void interceptsSaveMethod() throws Throwable {
127127
}
128128

129129
@Test // DATACMNS-1663
130-
public void interceptsDeleteMethod() throws Throwable {
130+
void interceptsDeleteMethod() throws Throwable {
131131
SomeEvent event = new SomeEvent();
132132
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
133133
mockInvocation(invocation, SampleRepository.class.getMethod("delete", Object.class), sample);
@@ -152,7 +152,7 @@ void doesNotInterceptNonSaveMethod() throws Throwable {
152152
}
153153

154154
@Test // DATACMNS-1663
155-
public void doesNotInterceptDeleteByIdMethod() throws Throwable {
155+
void doesNotInterceptDeleteByIdMethod() throws Throwable {
156156

157157
doReturn(SampleRepository.class.getMethod("deleteById", Object.class)).when(invocation).getMethod();
158158

@@ -204,7 +204,7 @@ void publishesEventsForCallToSaveWithIterable() throws Throwable {
204204
}
205205

206206
@Test // DATACMNS-1663
207-
public void publishesEventsForCallToDeleteWithIterable() throws Throwable {
207+
void publishesEventsForCallToDeleteWithIterable() throws Throwable {
208208

209209
SomeEvent event = new SomeEvent();
210210
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
@@ -217,6 +217,34 @@ public void publishesEventsForCallToDeleteWithIterable() throws Throwable {
217217
verify(publisher).publishEvent(any(SomeEvent.class));
218218
}
219219

220+
@Test // GH-2448
221+
void publishesEventsForCallToDeleteInBatchWithIterable() throws Throwable {
222+
223+
SomeEvent event = new SomeEvent();
224+
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
225+
mockInvocation(invocation, SampleRepository.class.getMethod("deleteInBatch", Iterable.class), sample);
226+
227+
EventPublishingMethodInterceptor//
228+
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
229+
.invoke(invocation);
230+
231+
verify(publisher).publishEvent(any(SomeEvent.class));
232+
}
233+
234+
@Test // GH-2448
235+
void publishesEventsForCallToDeleteAllInBatchWithIterable() throws Throwable {
236+
237+
SomeEvent event = new SomeEvent();
238+
MultipleEvents sample = MultipleEvents.of(Collections.singletonList(event));
239+
mockInvocation(invocation, SampleRepository.class.getMethod("deleteAllInBatch", Iterable.class), sample);
240+
241+
EventPublishingMethodInterceptor//
242+
.of(EventPublishingMethod.of(MultipleEvents.class), publisher)//
243+
.invoke(invocation);
244+
245+
verify(publisher).publishEvent(any(SomeEvent.class));
246+
}
247+
220248
@Test // DATACMNS-975
221249
void publishesEventsAfterSaveInvocation() throws Throwable {
222250

@@ -294,6 +322,17 @@ void publishesEventFromParameter() throws Throwable {
294322
verify(publisher, times(1)).publishEvent(event);
295323
}
296324

325+
@Test // GH-2448
326+
void doesNotEmitEventsFromPrimitiveValue() throws Throwable {
327+
328+
Method method = SampleRepository.class.getMethod("delete", Object.class);
329+
mockInvocation(invocation, method, "foo", MultipleEvents.of(Collections.emptySet()));
330+
331+
EventPublishingMethodInterceptor.of(EventPublishingMethod.of(MultipleEvents.class), publisher).invoke(invocation);
332+
333+
verify(publisher, never()).publishEvent(any());
334+
}
335+
297336
private static void mockInvocation(MethodInvocation invocation, Method method, Object parameterAndReturnValue)
298337
throws Throwable {
299338

@@ -322,17 +361,23 @@ void clearDomainEvents() {}
322361
}
323362

324363
@Value(staticConstructor = "of")
325-
static class OneEvent {
364+
private static class OneEvent {
326365
@Getter(onMethod = @__(@DomainEvents)) Object event;
327366
}
328367

329368
@Value
330-
static class SomeEvent {
369+
private static class SomeEvent {
331370
UUID id = UUID.randomUUID();
332371
}
333372

334373
interface SampleRepository extends CrudRepository<MultipleEvents, Long> {
335374

336375
MultipleEvents saveAndFlush(MultipleEvents events);
376+
377+
MultipleEvents delete(String name);
378+
379+
MultipleEvents deleteAllInBatch(Iterable<MultipleEvents> events);
380+
381+
MultipleEvents deleteInBatch(Iterable<MultipleEvents> events);
337382
}
338383
}

0 commit comments

Comments
 (0)