functional-programmingmonospring-webfluxspring-reactivespring-mono

Spring Webflux Mono<Void> always responds with successful response


I have a endpoint that takes id parameter and send delete product api to delete. productService.delete also returns Mono. The problem is when productService.delete method returns mono error, the endpoint always responds with http 200. And I can see error log about this mono error but my handler method responds http 200.

I have a AbstractErrorWebExceptionHandler to handler exception in my api. But error handler can't handle this problem because of Mono. When exceptions occurs in downstream, Spring webflux should aware of this error and does not respond with http 200.

    public Mono<ServerResponse> deleteProduct(ServerRequest request) {
     String id = request.pathVariable("id");
     Mono<Product> productMono = this.repository.findById(id);
     return productMono
            .flatMap(existingProduct ->
                    ServerResponse.noContent()
                            .build(productService.delete(existingProduct))
            );
}

Btw in the source code, it says the response will be committed when given publisher completes. But how about error complete ? I think Spring webflux does not check it is error signal or not. Just check for mono completes or not.

     * Build the response entity with no body.
     * The response will be committed when the given {@code voidPublisher} completes.
     * @param voidPublisher publisher publisher to indicate when the response should be committed
     * @return the built response
     */
    Mono<ServerResponse> build(Publisher<Void> voidPublisher);

Thank you in advance.


Solution

  • The problem is caused by using voidPublisher. If you create ServerResponse with void publisher, it simply will return http 200 even your downstream complete with error signal. It just does not care how your stream finish, it just care about completion of downstream.

    And if you want handle downstream error when you build your response just simple use

     ServerResponse.noContent()
        .body(productService.delete(existingProduct), Void.class)
    

    Now whenever any error occurred in downstream, server will respond with error.