Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebClients awaitBody throws Exception when expecting "Unit" #26491

Closed
blatobi opened this issue Feb 2, 2021 · 5 comments
Closed

WebClients awaitBody throws Exception when expecting "Unit" #26491

blatobi opened this issue Feb 2, 2021 · 5 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: superseded An issue that has been superseded by another type: documentation A documentation task

Comments

@blatobi
Copy link

blatobi commented Feb 2, 2021

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)
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Feb 2, 2021
@blatobi
Copy link
Author

blatobi commented Feb 2, 2021

Current workaround:

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

@rstoyanchev rstoyanchev added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Feb 3, 2021
@sdeleuze sdeleuze self-assigned this Feb 3, 2021
@sdeleuze sdeleuze added type: documentation A documentation task and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Feb 3, 2021
@sdeleuze sdeleuze added this to the 5.3.4 milestone Feb 3, 2021
@sdeleuze
Copy link
Contributor

sdeleuze commented Feb 3, 2021

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

@blatobi
Copy link
Author

blatobi commented Feb 3, 2021

2 thoughts:

  • awaitBody<Unit> still feels more accurate then 'toBodyless...`.
  • Even with a changed documentation, shouldn't the extension-method throw IllegalArgument, if the type Unit isn't valid?

gaerfield added a commit to gaerfield/spring-framework that referenced this issue Feb 3, 2021
allow WebClient.ResponseSpec.awaitBody()
to be used in combination with Type "Unit"
@gaerfield
Copy link
Contributor

@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...

@rstoyanchev rstoyanchev added the status: superseded An issue that has been superseded by another label Feb 4, 2021
@rstoyanchev rstoyanchev removed this from the 5.3.4 milestone Feb 4, 2021
@rstoyanchev
Copy link
Contributor

Superseded by #26504.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: superseded An issue that has been superseded by another type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

5 participants