Browse Source

Fix too restrictive entity callback matching.

We now properly support generic entity callbacks defined via lambda declarations.

Fixes #2822.
pull/2838/head
Oliver Drotbohm 3 years ago
parent
commit
979e0f401b
No known key found for this signature in database
GPG Key ID: C25FBFA0DA493A1D
  1. 19
      src/main/java/org/springframework/data/mapping/callback/EntityCallbackDiscoverer.java
  2. 28
      src/test/java/org/springframework/data/mapping/callback/DefaultEntityCallbacksUnitTests.java

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

@ -33,9 +33,7 @@ import org.springframework.beans.factory.config.BeanDefinition; @@ -33,9 +33,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.core.ResolvableTypeProvider;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@ -291,12 +289,9 @@ class EntityCallbackDiscoverer { @@ -291,12 +289,9 @@ class EntityCallbackDiscoverer {
static boolean supportsEvent(EntityCallback<?> callback, ResolvableType entityType,
ResolvableType callbackType) {
ResolvableType callbackInstanceType = callback instanceof EntityCallbackAdapter<?> provider
? provider.getResolvableType()
: ResolvableType.forInstance(callback);
return supportsEvent(callbackInstanceType, entityType)
&& callbackType.isAssignableFrom(callbackInstanceType);
return callback instanceof EntityCallbackAdapter<?> provider
? provider.supports(callbackType, entityType)
: callbackType.isInstance(callback) && supportsEvent(ResolvableType.forInstance(callback), entityType);
}
/**
@ -346,12 +341,10 @@ class EntityCallbackDiscoverer { @@ -346,12 +341,10 @@ class EntityCallbackDiscoverer {
* @author Oliver Drotbohm
*/
private static record EntityCallbackAdapter<T>(EntityCallback<T> delegate, ResolvableType type)
implements EntityCallback<T>, ResolvableTypeProvider {
implements EntityCallback<T> {
@NonNull
@Override
public ResolvableType getResolvableType() {
return type;
boolean supports(ResolvableType callbackType, ResolvableType entityType) {
return callbackType.isInstance(delegate) && supportsEvent(type, entityType);
}
}

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

@ -169,8 +169,7 @@ class DefaultEntityCallbacksUnitTests { @@ -169,8 +169,7 @@ class DefaultEntityCallbacksUnitTests {
@Test // DATACMNS-1467
void detectsMultipleCallbacksWithinOneClass() {
var ctx = new AnnotationConfigApplicationContext(
MultipleCallbacksInOneClassConfig.class);
var ctx = new AnnotationConfigApplicationContext(MultipleCallbacksInOneClassConfig.class);
var callbacks = new DefaultEntityCallbacks(ctx);
@ -184,6 +183,17 @@ class DefaultEntityCallbacksUnitTests { @@ -184,6 +183,17 @@ class DefaultEntityCallbacksUnitTests {
assertThat(ctx.getBean("callbacks", MultipleCallbacks.class).invocations).containsExactly("save", "convert");
}
@Test // GH-2822
void genericCallbackDiscoveredForObjectDeclaration() {
var ctx = new AnnotationConfigApplicationContext(SomeConfiguration.class);
var callbacks = new DefaultEntityCallbacks(ctx);
callbacks.callback(BeforeSaveCallback.class, new PersonDocument(null, "Walter", null));
assertThat(ctx.getBean(SomeConfiguration.class).invoked).isTrue();
}
@Configuration
static class MyConfig {
@ -312,4 +322,18 @@ class DefaultEntityCallbacksUnitTests { @@ -312,4 +322,18 @@ class DefaultEntityCallbacksUnitTests {
}
// GH-2822
@Configuration
static class SomeConfiguration {
boolean invoked = false;
@Bean
BeforeSaveCallback<Object> someGenericCallback() {
return it -> {
this.invoked = true;
return it;
};
}
}
}

Loading…
Cancel
Save