Description
Affects: 5.3.12
Webflux fails to apply the rule for controller methods returning void to suspend functions returning Unit. Code like the example below causes error messages in log: ERROR o.s.w.s.a.HttpWebHandlerAdapter - [882bce24-1] Error [java.lang.UnsupportedOperationException] for HTTP POST "/some/api/path", but ServerHttpResponse already committed (200 OK)
@PostMapping
suspend fun doSomething(response: ServerHttpResponse): Unit {
// ...
response.writeWith(/* ... */).awaitSingleOrNull()
}
Cause
InvocableHandlerMethod::invoke
wraps coroutine results with either mono or flux using CoroutinesUtils.invokeSuspendingFunction
, but getReturnType
simply returns Void.class
. This in turn causes reactiveAdapterRegistry.getAdapter
to return null
and isAsyncVoidReturnType
to return false
Workaround
Remove suspend modifier and replicate CoroutinesUtils.invokeSuspendingFunction
wrapping manually:
@PostMapping
fun doSomething(response: ServerHttpResponse) = mono(Dispatchers.Unconfined) {
// ...
response.writeWith(/* ... */).awaitSingleOrNull()
}
.filter { false }
.onErrorMap(InvocationTargetException::class.java, InvocationTargetException::getTargetException)
.cast(Void.TYPE)