Treat kotlin.Unit as void in web controllers

This commit fixes a regression introduced by gh-21139
via the usage of Kotlin reflection to invoke HTTP
handler methods. It ensures that kotlin.Unit is treated
as void by returning null.

It also polishes CoroutinesUtils to have a consistent
handling compared to the regular case, and adds related
tests to prevent future regressions.

Closes gh-31648
This commit is contained in:
Sébastien Deleuze
2023-11-22 12:40:32 +01:00
parent c329ed83ef
commit 441e210533
6 changed files with 79 additions and 4 deletions

View File

@@ -123,7 +123,7 @@ public abstract class CoroutinesUtils {
}
return KCallables.callSuspendBy(function, argMap, continuation);
})
.filter(result -> !Objects.equals(result, Unit.INSTANCE))
.filter(result -> result != Unit.INSTANCE)
.onErrorMap(InvocationTargetException.class, InvocationTargetException::getTargetException);
KClassifier returnType = function.getReturnType().getClassifier();

View File

@@ -20,6 +20,7 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.reactor.awaitSingle
import kotlinx.coroutines.reactor.awaitSingleOrNull
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.Test
import reactor.core.publisher.Flux
@@ -126,6 +127,24 @@ class CoroutinesUtilsTests {
Assertions.assertThatIllegalArgumentException().isThrownBy { CoroutinesUtils.invokeSuspendingFunction(context, method, this, "foo") }
}
@Test
fun invokeSuspendingFunctionReturningUnit() {
val method = CoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingUnit", Continuation::class.java)
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingleOrNull()).isNull()
}
}
@Test
fun invokeSuspendingFunctionReturningNull() {
val method = CoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingNullable", Continuation::class.java)
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingleOrNull()).isNull()
}
}
suspend fun suspendingFunction(value: String): String {
delay(1)
return value
@@ -146,4 +165,11 @@ class CoroutinesUtilsTests {
return value
}
suspend fun suspendingUnit() {
}
suspend fun suspendingNullable(): String? {
return null
}
}