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)

Comment From: koenpunt

I'm experiencing the same behavior. The workaround works well.

Comment From: sdeleuze

Looks like something we should fix even in 5.3.x.