Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebFlux functional: How to detect an empty Flux and return 404?

I'm having the following simplified handler function (Spring WebFlux and the functional API using Kotlin). However, I need a hint how to detect an empty Flux and then use noContent() for 404, when the Flux is empty.

fun findByLastname(request: ServerRequest): Mono<ServerResponse> {
    val lastnameOpt = request.queryParam("lastname")
    val customerFlux = if (lastnameOpt.isPresent) {
        service.findByLastname(lastnameOpt.get())
    } else {
        service.findAll()
    }
    // How can I detect an empty Flux and then invoke noContent() ?
    return ok().body(customerFlux, Customer::class.java)
}
like image 583
Juergen Zimmermann Avatar asked Aug 27 '17 10:08

Juergen Zimmermann


People also ask

How do you throw an error in WebFlux?

There are three ways that we can use onErrorResume to handle errors: Compute a dynamic fallback value. Execute an alternative path with a fallback method. Catch, wrap and re-throw an error, e.g., as a custom business exception.

What is backpressure in WebFlux?

Spring WebFlux provides an asynchronous non-blocking flow of reactive streams. The responsible for backpressure within Spring WebFlux is the Project Reactor. It internally uses Flux functionalities to apply the mechanisms to control the events produced by the emitter.

What is the difference between mono and flux?

Mono is more relatable to the Optional class in Java since it contains 0 or 1 value, and Flux is more relatable to List since it can have N number of values.


2 Answers

Use Flux.hasElements() : Mono<Boolean> function:

return customerFlux.hasElements()
                   .flatMap {
                     if (it) ok().body(customerFlux)
                     else noContent().build()
                   }
like image 133
RJ.Hwang Avatar answered Oct 01 '22 15:10

RJ.Hwang


From a Mono:

return customerMono
           .flatMap(c -> ok().body(BodyInserters.fromObject(c)))
           .switchIfEmpty(notFound().build());

From a Flux:

return customerFlux
           .collectList()
           .flatMap(l -> {
               if(l.isEmpty()) {
                 return notFound().build();

               }
               else {
                 return ok().body(BodyInserters.fromObject(l)));
               }
           });

Note that collectList buffers data in memory, so this might not be the best choice for big lists. There might be a better way to solve this.

like image 22
Brian Clozel Avatar answered Oct 01 '22 15:10

Brian Clozel