Include inherited non-Kotlin properties in KotlinBeanInfoFactory.

We now include properties from non-Kotlin supertypes if the supertype is not a Kotlin type and not Object.

Closes #2994
This commit is contained in:
Mark Paluch
2023-11-29 15:51:53 +01:00
parent 295d14e34d
commit 8a679156e0
2 changed files with 43 additions and 3 deletions

View File

@@ -28,10 +28,12 @@ import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.beans.BeanInfoFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.KotlinDetector;
import org.springframework.core.Ordered;
@@ -57,7 +59,7 @@ public class KotlinBeanInfoFactory implements BeanInfoFactory, Ordered {
}
KClass<?> kotlinClass = JvmClassMappingKt.getKotlinClass(beanClass);
List<PropertyDescriptor> pds = new ArrayList<>();
Set<PropertyDescriptor> pds = new LinkedHashSet<>();
for (KCallable<?> member : kotlinClass.getMembers()) {
@@ -69,6 +71,19 @@ public class KotlinBeanInfoFactory implements BeanInfoFactory, Ordered {
pds.add(new PropertyDescriptor(property.getName(), getter, setter));
}
}
Class<?> javaClass = beanClass;
do {
javaClass = javaClass.getSuperclass();
} while (KotlinDetector.isKotlinType(javaClass));
if (javaClass != Object.class) {
PropertyDescriptor[] javaPropertyDescriptors = BeanUtils.getPropertyDescriptors(javaClass);
pds.addAll(Arrays.asList(javaPropertyDescriptors));
}
return new SimpleBeanInfo() {
@Override
public BeanDescriptor getBeanDescriptor() {

View File

@@ -18,6 +18,9 @@ package org.springframework.data.util
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.BeanUtils
import org.springframework.data.repository.Repository
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport
import org.springframework.data.repository.core.support.RepositoryFactorySupport
/**
* Unit tests for [KotlinBeanInfoFactory].
@@ -81,6 +84,14 @@ class KotlinBeanInfoFactoryUnitTests {
assertThat(pds).extracting("name").contains("ordinal")
}
@Test // GH-2994
internal fun includesPropertiesFromJavaSupertypes() {
val pds = BeanUtils.getPropertyDescriptors(MyRepositoryFactoryBeanImpl::class.java)
assertThat(pds).extracting("name").contains("myQueryLookupStrategyKey", "repositoryBaseClass")
}
data class SimpleDataClass(val id: String, var name: String)
@JvmInline
@@ -98,4 +109,18 @@ class KotlinBeanInfoFactoryUnitTests {
Foo, Bar
}
class MyRepositoryFactoryBeanImpl<R, E, I>(repository: Class<R>) : RepositoryFactoryBeanSupport<R, E, I>(repository)
where R : Repository<E, I>, E : Any, I : Any {
private var myQueryLookupStrategyKey: String
get() = ""
set(value) {
}
override fun createRepositoryFactory(): RepositoryFactorySupport {
throw UnsupportedOperationException()
}
}
}