Skip to content

Commit bd64ed8

Browse files
committed
Fix too restrictive entity callback matching.
We now properly support generic entity callbacks defined via lambda declarations. Fixes #2822.
1 parent 136df13 commit bd64ed8

File tree

2 files changed

+32
-15
lines changed

2 files changed

+32
-15
lines changed

src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java

+6-13
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@
3333
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
3434
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
3535
import org.springframework.core.ResolvableType;
36-
import org.springframework.core.ResolvableTypeProvider;
3736
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
38-
import org.springframework.lang.NonNull;
3937
import org.springframework.lang.Nullable;
4038
import org.springframework.util.Assert;
4139
import org.springframework.util.ClassUtils;
@@ -291,12 +289,9 @@ static boolean supportsEvent(ResolvableType callbackType, ResolvableType entityT
291289
static boolean supportsEvent(EntityCallback<?> callback, ResolvableType entityType,
292290
ResolvableType callbackType) {
293291

294-
ResolvableType callbackInstanceType = callback instanceof EntityCallbackAdapter<?> provider
295-
? provider.getResolvableType()
296-
: ResolvableType.forInstance(callback);
297-
298-
return supportsEvent(callbackInstanceType, entityType)
299-
&& callbackType.isAssignableFrom(callbackInstanceType);
292+
return callback instanceof EntityCallbackAdapter<?> provider
293+
? provider.supports(callbackType, entityType)
294+
: callbackType.isInstance(callback) && supportsEvent(ResolvableType.forInstance(callback), entityType);
300295
}
301296

302297
/**
@@ -346,12 +341,10 @@ void discoverEntityCallbacks(BeanFactory beanFactory) {
346341
* @author Oliver Drotbohm
347342
*/
348343
private static record EntityCallbackAdapter<T>(EntityCallback<T> delegate, ResolvableType type)
349-
implements EntityCallback<T>, ResolvableTypeProvider {
344+
implements EntityCallback<T> {
350345

351-
@NonNull
352-
@Override
353-
public ResolvableType getResolvableType() {
354-
return type;
346+
boolean supports(ResolvableType callbackType, ResolvableType entityType) {
347+
return callbackType.isInstance(delegate) && supportsEvent(type, entityType);
355348
}
356349
}
357350

src/test/java/org/springframework/data/mapping/callback/DefaultEntityCallbacksUnitTests.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ void skipsInvocationUsingJava18ReflectiveTypeRejection() {
169169
@Test // DATACMNS-1467
170170
void detectsMultipleCallbacksWithinOneClass() {
171171

172-
var ctx = new AnnotationConfigApplicationContext(
173-
MultipleCallbacksInOneClassConfig.class);
172+
var ctx = new AnnotationConfigApplicationContext(MultipleCallbacksInOneClassConfig.class);
174173

175174
var callbacks = new DefaultEntityCallbacks(ctx);
176175

@@ -184,6 +183,17 @@ void detectsMultipleCallbacksWithinOneClass() {
184183
assertThat(ctx.getBean("callbacks", MultipleCallbacks.class).invocations).containsExactly("save", "convert");
185184
}
186185

186+
@Test // GH-2822
187+
void genericCallbackDiscoveredForObjectDeclaration() {
188+
189+
var ctx = new AnnotationConfigApplicationContext(SomeConfiguration.class);
190+
var callbacks = new DefaultEntityCallbacks(ctx);
191+
192+
callbacks.callback(BeforeSaveCallback.class, new PersonDocument(null, "Walter", null));
193+
194+
assertThat(ctx.getBean(SomeConfiguration.class).invoked).isTrue();
195+
}
196+
187197
@Configuration
188198
static class MyConfig {
189199

@@ -312,4 +322,18 @@ public Person onBeforeConvert(Person object) {
312322

313323
}
314324

325+
// GH-2822
326+
@Configuration
327+
static class SomeConfiguration {
328+
329+
boolean invoked = false;
330+
331+
@Bean
332+
BeforeSaveCallback<Object> someGenericCallback() {
333+
return it -> {
334+
this.invoked = true;
335+
return it;
336+
};
337+
}
338+
}
315339
}

0 commit comments

Comments
 (0)