Reputation: 848
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
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 asynchronouslyUpvotes: 1
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