-
Notifications
You must be signed in to change notification settings - Fork 681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calling PersistentPropertyAccessor.setProperty(…) on Kotlin data class objects with multiple copy methods can lead to ArrayIndexOutOfBoundsException #2324
Comments
The issue here is that the generated Kotlin class has two synthetic and two public The decompiled bytecode shows the following signatures:
Our detection assumed only a single copy method expecting that there is only one method taking all arguments. As it seems, we need to refine our assumptions because there are multiple copy methods and looking up a copy method solely by entity type isn't sufficient, we need to take into account which property should be copied. |
Going forward, the question arises, which copy method we should use. The question can be partially answered by presence/absence of a particular property. But what if a property is present in both copy methods as in the sample below. data class SampleDataClass(
val id: String?,
val userId: String,
val status: String,
val attempts: Int,
val createdAt: LocalDateTime,
val updatedAt: LocalDateTime,
val sessionId: String?
) {
fun copy(
status: String,
updatedAt: LocalDateTime,
sessionId: String,
attempts: Int = this.attempts
) = SampleDataClass(
this.id,
this.userId,
status,
attempts,
this.createdAt,
updatedAt,
sessionId
)
} |
This change bears a certain risk of breaking existing application code due to the refined copy method lookup. Therefore, we're backporting it to |
We now resolve the copy method for Kotlin data classes that match the primary constructor. Previously, copy method resolution could find a secondary copy method as we didn't check for the primary constructor structure (parameter names and types). Closes #2324.
Reduce test method visibility. See #2324.
Reduce test method visibility. See #2324.
Use ResolvableType for type assignability check when resolving Type from a KType. See #2324.
Use ResolvableType for type assignability check when resolving Type from a KType. See #2324.
We now resolve only the raw class when checking if a primary constructor argument is assignable to method parameters of the synthetic copy method. Previously we used ResolvableType's assignability check which considered generic type arguments. As the type resolution between the KType and copy method type is not symmetric, the check only succeeded in cases where both types could be resolved to the same type/assignable type. Using projections or Any caused asymmetric resolution and therefor the assignability check returned non-assignable. Closes #2324.
There is flaky problem which leads to ArrayIndexOutOfBoundsException when dealing with Kotlin data classes with copy method having default values as entities in ClassGeneratingPropertyAccessorFactory.PropertyAccessorClassGenerator.generateCustomAccessorClass.
Please check this demo which reproduces the issue (just try to run ProblemDemoTests for several times and you'll receive ArrayIndexOutOfBoundsException): https://github.com/tano/aioob-demo/blob/master/src/test/kotlin/org/springframework/data/mapping/model/ProblemDemoTests.kt
Removing
attempts: Int = this.attempts
default parameter solves the issues.Version details:
Java: openjdk version "11.0.9.1" 2020-11-04 LTS
Kotlin: 1.4.30
spring-data-commons: 2.4.5
The text was updated successfully, but these errors were encountered: