Skip to content

BeanUtils.getPropertyDescriptors(…) for Kotlin class with Java superclass does not include properties from its superclass #2994

Closed
@cmdjulian

Description

@cmdjulian

After updating to Spring Boot 3.2, my Kotlin app does not start anymore with an exception of Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'queryLookupStrategyKey' of bean class [com.example.demo.JpaRepositoryFactoryBeanImpl]: Bean property 'queryLookupStrategyKey' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?.

After debugging for some time I found out that in 3.2 there seems to be some new property introspection for kotlin classes and their properties are active. The problem seems to be, that the setters from the super class, in that case JpaRepositoryFactoryBean are not recognized as they are not Kotlin properties.

I can work around that by including the following code:

private var queryLookupStrategyKey: Key
    get() = throw UnsupportedOperationException()
    @JvmName("setQueryLookupStrategyKeyKt") set(value) {
        super.setQueryLookupStrategyKey(value)
    }
private var lazyInit: Boolean
    get() = throw UnsupportedOperationException()
    @JvmName("setLazyInitKt") set(value) {
        super.setLazyInit(value)
    }
private var namedQueries: NamedQueries
    get() = throw UnsupportedOperationException()
    @JvmName("namedQueriesKt") set(value) {
        super.setNamedQueries(value)
    }
private var repositoryFragments: RepositoryFragments
    get() = throw UnsupportedOperationException()
    @JvmName("setRepositoryFragmentsKt") set(value) {
        super.setRepositoryFragments(value)
    }
private var transactionManager: String
    get() = throw UnsupportedOperationException()
    @JvmName("setTransactionManagerKt") set(value) {
        super.setTransactionManager(value)
    }
private var entityManager: EntityManager
    get() = throw UnsupportedOperationException()
    @JvmName("setEntityManagerKt") set(value) {
        super.setEntityManager(value)
    }
private var escapeCharacter: Char
    get() = throw UnsupportedOperationException()
    @JvmName("setEscapeCharacterKt") set(value) {
        super.setEscapeCharacter(value)
    }
private var mappingContext: MappingContext<*, *>
    get() = throw UnsupportedOperationException()
    @JvmName("setMappingContextKt") set(value) {
        super.setMappingContext(value)
    }
private var enableDefaultTransactions: Boolean
    get() = throw UnsupportedOperationException()
    @JvmName("setEnableDefaultTransactionsKt") set(value) {
        super.setEnableDefaultTransactions(value)
    }

Another workaround is writing that class in java, but this defeats the purpose of using Kotlin in the first place.

Attached is a minimal reproducible example: kotlin-jpa-bug.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions