-
Notifications
You must be signed in to change notification settings - Fork 38.3k
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
Support Kotlin value (JvmInline) classes as suspend
handler method arguments
#27345
Comments
suspend
handler method arguments
I have written an inline value class converter and included it into my private class KotlinInlineClassConverter(
private val conversionService: ConversionService,
) : ConditionalGenericConverter {
override fun getConvertibleTypes() = setOf(ConvertiblePair(Any::class.java, Any::class.java))
override fun matches(sourceType: TypeDescriptor, targetType: TypeDescriptor): Boolean {
val targetClass = targetType.type
if (!targetClass.isInlineValueClass()) return false
return conversionService.canConvert(sourceType, targetClass.wrappedValueTypeDescriptor())
}
override fun convert(source: Any?, sourceType: TypeDescriptor, targetType: TypeDescriptor): Any? {
val targetClass = targetType.type
val convertedSource = conversionService.convert(source, sourceType, targetClass.wrappedValueTypeDescriptor())
?: return null
return targetClass.kotlin.primaryConstructor!!.call(convertedSource)
}
private fun Class<*>.isInlineValueClass() =
isKotlinType(this) && annotations.any { it is JvmInline }
private fun Class<*>.wrappedValueTypeDescriptor() =
TypeDescriptor.valueOf(kotlin.primaryConstructor!!.parameters.single().type.jvmErasure.java)
} but this does not seem to work because the |
Hello, is there any update on this issue? Is it being reviewed? Thanks |
Related to #28638. |
I am currently blocked on this one by a Kotlin reflection behavior that I can't understand. The invocation of I have created a dedicated Kotlin focused repro with 8 unit tests, and only one is failing. I am waiting for feedback from the Kotlin team to move forward. |
This is a Kotlin bug : KT-58887. |
The underlying blocking bug has been solved in Kotlin 1.9.20-RC2 via KT-47973, the next issue is on Spring side in order to support mangled method names (probably via leveraging Kotlin reflection rather than Java one for the function invocation). |
With Spring Boot 3.2 and Spring Framework 6.1 this bug is not restricted to It happens in the @RestController
class MyController {
@GetMapping("/item/{itemId}")
fun getItem(@PathVariable itemId: ItemId) = itemId
}
@JvmInline
value class ItemId(val id: String) Reproduce: curl http://localhost:8080/item/1 Solution: Exception:
|
Thanks for the update, as of Spring Framework 6.1, we are now using Kotlin reflection instead of Java reflection for all web handler method invocations (in order to support various Kotlin use cases like default parameter values etc.) but we hit here another Kotlin bug, namely KT-64097, which hopefully should fixed pretty fast as Kotlin team works on it actively. Please track the Kotlin issue for the resolution of this issue, and will as well and check everything is fine on Spring side once fixed. This issue is also likely a duplicate of #31698. As a consequence, I close this issue on Spring side since this should be fixed on Kotlin side. |
Affects: Spring Framework 5.3.9, Spring Boot 2.5.4
Using a
@JvmInline value class
as a handler method argument fails with the following:My best guess is this happens because, say with the example below:
at runtime the getProduct parameter type when viewed from Java reflection is the wrapped value type (
String
) but when viewed from Kotlin reflection, the parameter is the wrapper value class (ProductId
). The error is thrown when the function is invoked from kotlin reflection withString
instance arguments (contributed by the RequestParam resolver) but the kotlin reflection API expects theProductId
instance (which it automatically unboxes, exception is thrown here)The text was updated successfully, but these errors were encountered: