micronaut-projects / micronaut-reactor

Integration between Micronaut and Reactor
Apache License 2.0
18 stars 7 forks source link

Global @Error doesn't work when Controller return is Flux #238

Open luisospina-sealed opened 1 year ago

luisospina-sealed commented 1 year ago

Expected Behavior

When an endpoint does return a Flux<Something> if an error occurs and there's a global @Error handler defined it should catch the exception.

Actual Behaviour

Exception is not captured and a 500 error is returned as the response of the HTTP request

Steps To Reproduce

Having the following Global @Error

@Error(global = true)
public HttpResponse<JsonError> entityNotFoundHandler(HttpRequest<?> request, EntityNotFoundException exception) {
    JsonError error = new JsonError("Entity Not Found: " + exception.getMessage());
    return HttpResponse.<JsonError>status(HttpStatus.NOT_FOUND, "Not found")
            .body(error);
}

And the following Endpoint inside a Controller

@Get
Flux<Entity> findAllEntities() {
    return service.findAll(); -> This line throws EntityNotFoundException
}

The code in the global @Error above is not being executed and the Exception is propagated to the HTTP response which ends up in a 500 status error instead of the 404 specified in the Error handling.

Note that the following works perfect (when Mono is the return type)

@Get
Mono<Entity> findById() {
    return service.findById(); -> This line throws EntityNotFoundException;
}

Environment Information

No response

Example Application

No response

Version

3.6.0

jeremyg484 commented 8 months ago

I have tested and verified that the error handler gets invoked as expected in both Micronaut 3.10.1 and 4.1.5.

Note that in the case of the controller method returning a Flux, the method must also be annotated with @SingleResult, otherwise Micronaut treats it as a chunked response.

When writing a chunked response, the current implementation does not invoke the @Error handler in the case of a Flux.error() (likely because it is difficult to know if any data has already been written to the response body).