Skip to content

Kotlin: Invoked method is not a property accessor exception when using method name query derivation and switching from Spring Boot 3.2.8 to version 3.2.9 #3771

Closed
@mmrsic

Description

@mmrsic

Please investigate whether the following issue has a known workaround that I could use to mitigate it and/or whether it will be fixed in a follwoing 3.2.x version.

Issue

When accessing a JPA Spring Data repository with automatic code generation, the Spring Boot 3.2.9 version raises an IllegalArgumentException: Invoked method is not a property accessor".
Changing soleley the Spring Boot version from 3.2.9 back to 3.2.8 fixes the issue. Using any 3.2.x version where x between 9 and 12 reproduces the exception.

Stacktrace:

Invoked method is not a property accessor
java.lang.IllegalStateException: Invoked method is not a property accessor
	at org.springframework.data.projection.PropertyAccessingMethodInterceptor.invoke(PropertyAccessingMethodInterceptor.java:66)
	at org.springframework.data.projection.ProjectingMethodInterceptor.invoke(ProjectingMethodInterceptor.java:71)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.data.projection.ProxyProjectionFactory$TargetAwareMethodInterceptor.invoke(ProxyProjectionFactory.java:243)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
	at jdk.proxy3/jdk.proxy3.$Proxy147.getChildId(Unknown Source)
	at org.springboot.issues.springbootdata329issue.ApplicationTests.testInvokedMethodIsNotAPropertyAccessorSpringBoot329(ApplicationTests.kt:26)

Test case to reproduce

import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest


@DataJpaTest
class ApplicationTests(@Autowired val repo: SpringBootTestRepository) {

    /**
     * This test case works when using Spring Boot 3.2.8 but fails when using version 3.2.9.
     */
    @Test
    fun testInvokedMethodIsNotAPropertyAccessorSpringBoot329() {
        val childId = "childId"
        val child = SpringBootTestChildEntity(childId)
        val parent = SpringBootTestParentEntity(parentId = "parentId", children = mutableListOf(child))
        repo.save(parent)

        // act
        val result = repo.findByChildrenChildId(childId) // children is the parent entity's attribute, and childId is the child entity's attribute, see JPA classes below.

        // assert
        assert(result.isNotEmpty())
        result.forEach {
            val children = it.children
            children.childId // This fails with IllegalStateException for Spring Boot 3.2.9
        }
    }
}

JPA Repository

import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface SpringBootTestRepository : JpaRepository<SpringBootTestParentEntity, String> {

    fun findByChildrenChildId(wantedChildId: String): List<SpringBootTestParentInterface>
}

interface SpringBootTestParentInterface {

    val parentId: String
    val children: SpringBootTestChildInterface

}

interface SpringBootTestChildInterface {

    val childId: String
}

Entities

import jakarta.persistence.*

@Entity(name = "ParentEntity")
@Table(name = "PARENT_TABLE")
open class SpringBootTestParentEntity() {

    private var parentId: String? = null
    private var children: MutableList<SpringBootTestChildEntity> = ArrayList()

    constructor(parentId: String, children: MutableList<SpringBootTestChildEntity>) : this() {
        this.parentId = parentId
        this.children = children
    }

    @Id
    open fun getParentId() = parentId
    open fun setParentId(id: String) {
        parentId = id
    }

    @ElementCollection(targetClass = SpringBootTestChildEntity::class, fetch = FetchType.EAGER)
    @CollectionTable(
        name = "CHILD_TABLE",
        joinColumns = [JoinColumn(name = "parentId", referencedColumnName = "parentId")],
    )
    open fun getChildren() = children

    open fun setChildren(newChildren: MutableList<SpringBootTestChildEntity>) {
        children = newChildren
    }
}

@Embeddable
@Table(name = "CHILD_TABLE")
open class SpringBootTestChildEntity() {

    constructor(id: String) : this() {
        childId = id
    }

    private var childId: String = ""

    open fun getChildId() = childId

    open fun setChildId(newId: String) {
        childId = newId
    }
}

### Gradle
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.9.25'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.9.25'
    id 'org.springframework.boot' version '3.2.9'
    id 'io.spring.dependency-management' version '1.1.7'
    id 'org.jetbrains.kotlin.plugin.jpa' version '1.9.25'
}

group = 'org.springboot.issues'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.jetbrains.kotlin:kotlin-reflect'

    testImplementation 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

kotlin {
    compilerOptions {
        freeCompilerArgs.addAll '-Xjsr305=strict'
    }
}

allOpen {
    annotation 'jakarta.persistence.Entity'
    annotation 'jakarta.persistence.MappedSuperclass'
    annotation 'jakarta.persistence.Embeddable'
}

tasks.named('test') {
    useJUnitPlatform()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions