Closed
Description
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()
}