1
votes

Small question regarding Spring Boot Webflux 2.5.0 and how to deal with a http response without body.

By "without body" I mean:

For instance, a web application I consume the rest API and have no control returns:

HTTP status code 200
HTTP body {"foo": "bar"}

With Spring Webflux, we can easily write something like:

public Mono<FooBar> sendRequest(SomeRequest someRequest) {
        return webClient.mutate()
                        .baseUrl("https://third-party-rest-api.com:443")
                        .build()
                        .post()
                        .uri(/someroute)
                        .body(BodyInserters.fromValue(someRequest))
                        .retrieve().bodyToMono(FooBar.class);
}

public class FooBar {
    
    private String foo;

    //getter setters

}

In order to get the POJO corresponding to the http body.

Now, another third party API I am consuming only return HTTP 200 as status response. I would like to emphasize, there is no HTTP body. It is not the empty JSON {}.

Hence, I am a bit lost, and do not know what to put here. Especially with the goal of avoiding the mono empty.

public Mono<WhatToPutHerePlease> sendRequest(SomeRequest someRequest) {
        return webClient.mutate()
                        .baseUrl("https://third-party-rest-api.com:443")
                        .build()
                        .post()
                        .uri(/someroute-with-no-http-body-response)
                        .body(BodyInserters.fromValue(someRequest))
                        .retrieve()
                        .bodyToMono(WhatToPutHerePlease.class);
}

Any help please?

Thank you

2
Can you return a Mono containing ResponseEntity.noContent()?chrylis -cautiouslyoptimistic-

2 Answers

2
votes

Hence, I am a bit lost, and do not know what to put here.

The response is empty, so there's nothing for your webclient to parse and return a value. The resulting Mono is thus always going to be empty, whatever generic type you use.

We have a special type that essentially says "this will always be empty" - Void (note the capital V.) So if you want to return an empty Mono, keeping the rest of the code the same, that's the type you should use.

Alternatively, if you don't want to return an empty publisher, then you might consider using .retrieve().toBodiLessEntity() instead of .retrieve().bodyToMono() - this will return a Mono<ResponseEntity<Void>>. The resulting body will obviously still be empty, but the response entity returned will enable you to extract information such as the response code & header information, should that be useful.

1
votes

toBodylessEntity() seems to suit your needs:

It returns a Mono<ResponseBody<Void>>.

With a (void rest) controller like:

@RestController 
@SpringBootApplication
public class Demo {
  public static void main(String[] args) {
    SpringApplication.run(Demo.class, args);
    // ... 
  }
  @GetMapping("/")
  public void empty() {

  }
}

and a:

public class ReactiveClient {

  Mono<ResponseEntity<Void>> mono = WebClient.create("http://localhost:8080")
    .get()
    .retrieve()
    .toBodilessEntity();

  // blocking/synchronous
  public ResponseEntity<Void> get() {
    return mono.block();
  }
}

We can:

ReactiveClient reactiveClient = new ReactiveClient();
System.out.println(reactiveClient.get()); // or something else