Sam Fisher
Sam Fisher

Reputation: 848

What response type is better to return from reactive endpoint if we return multiple objects?

If we use reactive approach in Spring we can return Flux/Mono type in methods. So in controller it's good to wrap response ResponseEntity and return it and in case of endpoints which return one object we can write in reactive next code:

@GetMapping(value = "/to-do/{toDoId}", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public Mono<ResponseEntity<ToDo>> getToDo(@Valid @PathVariable Long toDoId) {
        return repository.findById(toDoId)
                .map(ResponseEntity::ok);
    }

But what if we want to return Flux? After some experiments I found this solution:

@GetMapping(value = "/to-do", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public ResponseEntity<Flux<ToDo>> getToDos() {
        return ResponseEntity.ok().body(
                repository.findAll()
        );
    }

But if I understand correct here in such format, response like ResponseEntity<Flux<ToDo>> will be blocking? So it's better to do something like <Flux<ResponseEntity<ToDo>> ? If it's so, how to get it? I should subscribe?

Upvotes: 0

Views: 847

Answers (2)

kerbermeister
kerbermeister

Reputation: 4281

There are multiple ways you can return value using ResponseEntity from your reactive controller:

Publisher can be Mono or Flux

  • ResponseEntity<Publisher<T>> - this makes the response status and headers known immediately while the body is provided asynchronously at some later point of time.
  • Publisher<ResponseEntity<T>> - this provides all three: response status, headers, and body, asynchronously at some later point of time. It allows the headers and response status to vary depending on the outcome of asynchronous handling.

Also it is possible to use the following construct, less common, though:

  • Mono<ResponseEntity<Publisher<T>>> - provide the response status and headers asynchronously first, and later response body, also asynchronously

Upvotes: 1

codependent
codependent

Reputation: 24472

It seems you don't really use the ResponseEntity to customize the reponse status so, why not just return Mono or Flux?

@GetMapping(value = "/to-do/{toDoId}", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public Mono<ToDo> getToDo(@Valid @PathVariable Long toDoId) {
        return repository.findById(toDoId);
    }

@GetMapping(value = "/to-do", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
    public Flux<ToDo> getToDos() {
        return repository.findAll();
    }

In any case, according to the documentation it's perfectly fine to return ResponseEntity<Mono> and ResponseEntity<Flux>, both will provide an asynchronous, non-blocking response:

ResponseEntity<Mono> or ResponseEntity<Flux> make the response status and headers known immediately while the body is provided asynchronously at a later point. Use Mono if the body consists of 0..1 values or Flux if it can produce multiple values.

Upvotes: 2

Related Questions