Affected component: spring-webflux Version: 5.3.2

When using the Kotlin-Extensions for WebClient on Endpoints that do not return any data, awaitBody<Unit> is throwing java.util.NoSuchElementException: No value received via onNext for awaitSingle.

I was thinking I may accidentally misuse the API, but spring-docs document also this call:

val personDeferred: Deferred<Person> = ...

client.post()
        .uri("/persons/{id}", id)
        .contentType(MediaType.APPLICATION_JSON)
        .body<Person>(personDeferred)
        .retrieve()
        .awaitBody<Unit>()

Reproduction: Given the following controller:

import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*

@RestController
class TestController {

    @PostMapping("/test")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    fun postTest() {}

}

And this Unit-Test:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
internal class TestControllerTest(
    @LocalServerPort private val port : Int
) {

    @Test
    fun postTest()  = runBlocking {
        WebClient.create("localhost:$port/test")
            .post()
            .retrieve()
            .awaitBody<Unit>()
    }

}

The test will fail with

java.util.NoSuchElementException: No value received via onNext for awaitSingle

    at |b|b|b(Coroutine boundary.|b(|b)
    at TestControllerTest$deleteTest$1.invokeSuspend(TestControllerTest.kt:52)
Caused by: java.util.NoSuchElementException: No value received via onNext for awaitSingle
    at kotlinx.coroutines.reactive.AwaitKt$awaitOne$$inlined$suspendCancellableCoroutine$lambda$1.onComplete(Await.kt:181)
    at reactor.core.publisher.StrictSubscriber.onComplete(StrictSubscriber.java:123)

Comment From: blatobi

Current workaround:

WebClient.create("localhost:$port/test")
            .post()
            .retrieve()
            .toBodilessEntity()
            .awaitSingleOrNull()

Comment From: sdeleuze

You should probably use ClientResponse.awaitBodilessEntity() for that use case, I will update the documentation accordingly.

Comment From: blatobi

2 thoughts: * awaitBody<Unit> still feels more accurate then 'toBodyless.... * Even with a changed documentation, shouldn't the extension-method throwIllegalArgument, if the typeUnit` isn't valid?

Comment From: gaerfield

@sdeleuze I have created a pull-request with allowing awaitBody<Unit>() and introduced also awaitBodilessEntity like in ClientResponse.awaitBodilessEntity(). Let me know what you think...

Comment From: rstoyanchev

Superseded by #26504.