Problem: The below code throws the following error on Spring Boot 3.4.0 but not on Spring Boot 3.3.6:
java.lang.ClassCastException: class kotlin.Unit cannot be cast to class kotlin.Result (kotlin.Unit and kotlin.Result are in unnamed module of loader 'app')
interface Repo {
suspend fun fetch(): Result<Unit>
}
@Repository
class RepoImpl : Repo {
override suspend fun fetch(): Result<Unit> {
return Result.success(Unit)
}
}
@RestController
class HomeAPI(private val repo: Repo) {
@GetMapping("/")
suspend fun index(): ResponseEntity<Unit> {
repo.fetch().getOrThrow()
return ResponseEntity(HttpStatus.OK)
}
}
More details:
This seems to occur when I add the spring-boot-starter-data-r2dbc
related dependencies
Minimal Repo: https://github.com/msotho/castissue.git
Includes a Unit Test:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
internal class HomeAPITest @Autowired constructor(private val webTestClient: WebTestClient) {
@Test
fun `should return http status OK`() {
webTestClient
.get()
.uri("/")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk
}
}
Comment From: wilkinsona
Thanks for the sample.
As far as I can tell, this is a regression in Spring Framework 6.2. The problem occurs with Spring Boot 3.3.6 when the Spring Framework version is overridden to 6.2.0:
ext {
set("spring-framework.version", "6.2.0")
}
We'll transfer this issue so that the Framework team can continue the investigation.
Comment From: msotho
Setting Spring Boot 3.3.6 then it works. So it seems it's introduced by 3.4.0
Comment From: sdeleuze
It was indeed a Spring Framework 6.2 regression. Kotlin value class unboxing was done at CoroutinesUtils
level, which is a good fit for InvocableHandlerMethod
use case, but not for other ones like AopUtils
involved in the repro.
This commit moves such unboxing to InvocableHandlerMethod
(both on WebMVC and WebFlux) in order to keep the HTTP response body support while fixing other regressions.
Spring Framework 7 will provide utility methods allowing to reduce the code duplication we have currently.