diff --git a/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java b/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java index 8fc946944..d304a4142 100644 --- a/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java +++ b/src/main/java/org/springframework/data/util/KotlinBeanInfoFactory.java @@ -48,10 +48,15 @@ public class KotlinBeanInfoFactory implements BeanInfoFactory, Ordered { @Override public BeanInfo getBeanInfo(Class beanClass) throws IntrospectionException { + if (beanClass.isInterface()) { + return null; // back-off to leave interface-based properties to the default mechanism. + } + if (!KotlinDetector.isKotlinReflectPresent() || !KotlinDetector.isKotlinType(beanClass)) { return null; } + KClass kotlinClass = JvmClassMappingKt.getKotlinClass(beanClass); List pds = new ArrayList<>(); diff --git a/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt b/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt index 5f6fb1de9..ddf63f368 100644 --- a/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt +++ b/src/test/kotlin/org/springframework/data/util/KotlinBeanInfoFactoryUnitTests.kt @@ -65,6 +65,14 @@ class KotlinBeanInfoFactoryUnitTests { assertThat(pds[0].writeMethod).isNull() } + @Test // GH-2964 + internal fun backsOffForInterfaces() { + + val pds = BeanUtils.getPropertyDescriptors(FirstnameOnly::class.java) + + assertThat(pds).hasSize(1).extracting("name").containsOnly("firstname") + } + data class SimpleDataClass(val id: String, var name: String) @JvmInline @@ -74,4 +82,8 @@ class KotlinBeanInfoFactoryUnitTests { data class WithOptionalValueClass(val address: EmailAddress? = EmailAddress("un@known")) + interface FirstnameOnly { + fun getFirstname(): String + } + }