diff --git a/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java b/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java index fd373d94e..7aea48dc1 100644 --- a/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java +++ b/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java @@ -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 pds = new ArrayList<>(); + Set 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() { diff --git a/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt b/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt index 04a3663b6..03c8ee34e 100644 --- a/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt +++ b/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt @@ -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(repository: Class) : RepositoryFactoryBeanSupport(repository) + where R : Repository, E : Any, I : Any { + + private var myQueryLookupStrategyKey: String + get() = "" + set(value) { + + } + + override fun createRepositoryFactory(): RepositoryFactorySupport { + throw UnsupportedOperationException() + } + } + }