Skip to content

Commit 9fd8bce

Browse files
committed
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
1 parent 5ac30bf commit 9fd8bce

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
import java.beans.PropertyDescriptor;
2929
import java.beans.SimpleBeanInfo;
3030
import java.lang.reflect.Method;
31-
import java.util.ArrayList;
32-
import java.util.List;
31+
import java.util.Arrays;
32+
import java.util.LinkedHashSet;
33+
import java.util.Set;
3334

3435
import org.springframework.beans.BeanInfoFactory;
36+
import org.springframework.beans.BeanUtils;
3537
import org.springframework.core.KotlinDetector;
3638
import org.springframework.core.Ordered;
3739

@@ -57,7 +59,7 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
5759
}
5860

5961
KClass<?> kotlinClass = JvmClassMappingKt.getKotlinClass(beanClass);
60-
List<PropertyDescriptor> pds = new ArrayList<>();
62+
Set<PropertyDescriptor> pds = new LinkedHashSet<>();
6163

6264
for (KCallable<?> member : kotlinClass.getMembers()) {
6365

@@ -69,6 +71,19 @@ public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
6971
pds.add(new PropertyDescriptor(property.getName(), getter, setter));
7072
}
7173
}
74+
75+
Class<?> javaClass = beanClass;
76+
do {
77+
78+
javaClass = javaClass.getSuperclass();
79+
} while (KotlinDetector.isKotlinType(javaClass));
80+
81+
if (javaClass != Object.class) {
82+
83+
PropertyDescriptor[] javaPropertyDescriptors = BeanUtils.getPropertyDescriptors(javaClass);
84+
pds.addAll(Arrays.asList(javaPropertyDescriptors));
85+
}
86+
7287
return new SimpleBeanInfo() {
7388
@Override
7489
public BeanDescriptor getBeanDescriptor() {

src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt

+25
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ package org.springframework.data.util
1818
import org.assertj.core.api.Assertions.assertThat
1919
import org.junit.jupiter.api.Test
2020
import org.springframework.beans.BeanUtils
21+
import org.springframework.data.repository.Repository
22+
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport
23+
import org.springframework.data.repository.core.support.RepositoryFactorySupport
2124

2225
/**
2326
* Unit tests for [KotlinBeanInfoFactory].
@@ -81,6 +84,14 @@ class KotlinBeanInfoFactoryUnitTests {
8184
assertThat(pds).extracting("name").contains("ordinal")
8285
}
8386

87+
@Test // GH-2994
88+
internal fun includesPropertiesFromJavaSupertypes() {
89+
90+
val pds = BeanUtils.getPropertyDescriptors(MyRepositoryFactoryBeanImpl::class.java)
91+
92+
assertThat(pds).extracting("name").contains("myQueryLookupStrategyKey", "repositoryBaseClass")
93+
}
94+
8495
data class SimpleDataClass(val id: String, var name: String)
8596

8697
@JvmInline
@@ -98,4 +109,18 @@ class KotlinBeanInfoFactoryUnitTests {
98109
Foo, Bar
99110
}
100111

112+
class MyRepositoryFactoryBeanImpl<R, E, I>(repository: Class<R>) : RepositoryFactoryBeanSupport<R, E, I>(repository)
113+
where R : Repository<E, I>, E : Any, I : Any {
114+
115+
private var myQueryLookupStrategyKey: String
116+
get() = ""
117+
set(value) {
118+
119+
}
120+
121+
override fun createRepositoryFactory(): RepositoryFactorySupport {
122+
throw UnsupportedOperationException()
123+
}
124+
}
125+
101126
}

0 commit comments

Comments
 (0)