web-dev-qa-db-fra.com

WebFlux fonctionnel: Comment détecter un Flux vide et retourner 404?

J'ai la fonction de gestionnaire simplifiée suivante (Spring WebFlux et l'API fonctionnelle utilisant Kotlin). Cependant, j'ai besoin d'un indice sur la façon de détecter un flux vide, puis d'utiliser noContent () pour 404, lorsque le flux est vide.

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)
}
7
Juergen Zimmermann

À partir d'un Mono:

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

À partir d'un Flux:

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

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

Notez que collectList met les données en mémoire tampon, donc ce n'est peut-être pas le meilleur choix pour les grandes listes. Il pourrait y avoir une meilleure façon de résoudre ce problème.

19
Brian Clozel

En plus de la solution de Brian, si vous ne voulez pas faire une vérification vide de la liste tout le temps, vous pouvez créer une fonction d'extension:

fun <R> Flux<R>.collectListOrEmpty(): Mono<List<R>> = this.collectList().flatMap {
        val result = if (it.isEmpty()) {
            Mono.empty()
        } else {
            Mono.just(it)
        }
        result
    }

Et appelez-le comme vous le faites pour le Mono:

return customerFlux().collectListOrEmpty()
                     .switchIfEmpty(notFound().build())
                     .flatMap(c -> ok().body(BodyInserters.fromObject(c)))
4
zennon

Utilisez la fonction Flux.hasElements() : Mono<Boolean>:

return customerFlux.hasElements()
                   .flatMap {
                     if (it) ok().body(customerFlux)
                     else noContent().build()
                   }
3
RJ.Hwang

Je ne sais pas pourquoi personne ne parle d'utiliser la fonction hasElements () de Flux.Java qui retournerait un Mono.

3
ayush prashar