7

I'm trying to understand if this is a feature or a bug... :-)

For the below controller and exception mapper, for a rest client that will fail with a 401 response, I would expect the exception handler to be invoked for both cases. However it's not invoked for the WebApplicationException. Why is that and how are you meant to register an exception handler for them cases. This is using Quarkus version 0.21.2

@Path("/failable")
public class FailableResource {

  @Inject
  @RestClient
  private SomeHttpClient httpClient;

  @GET
  @Path("fails")
  @Produces(MediaType.TEXT_PLAIN)
  public String fails() {
    try {
      return httpClient.someQuery();
    } catch (Exception e) {
      e.printStackTrace();
      throw e;
    }
  }

  @GET
  @Path("works")
  @Produces(MediaType.TEXT_PLAIN)
  public String works() {
    try {
      return httpClient.someQuery();
    } catch (Exception e) {
      e.printStackTrace();
      throw new IllegalStateException("Not a WebApplicationException");
    }
  }
}

And the ExceptionMapper

@Provider
public class HandleMySillyError implements ExceptionMapper<Throwable> {

  @Override
  public Response toResponse(Throwable e) {
    e.printStackTrace();
    return Response.ok("Some handled response").build();
  }
}
bmooney
  • 391
  • 6
  • 15
  • If I understand correctly, in case of a 401 unauthorized your ExceptionMapper is not called. I think this is because in Quarkus, 401 is not handled via an UnauthorizedException but directly via a filter in the reteasy extension. I will raise this issue on the mailing list. – loicmathieu Sep 13 '19 at 07:53
  • Just to clarify, @loicmathieu, the 401 is from the rest client. And the exception is catchable in the controller as per the above code. I'm just not sure why re-throwing as a WebApplicationException skips the ExceptionMapper, where-as wrapping in a different exception is handled by the ExceptionMapper. Thanks for looking though. – bmooney Sep 13 '19 at 08:50
  • Ah fun, I mis-understood it and discover an other limitation regarding how Quarkus currently handle 401 and 403 inside it's own security mechanism. So regarding your error, it should works. Can you create a reproducer and open an issue the Quarkus Github repo? – loicmathieu Sep 13 '19 at 15:19
  • Cheers @loicmathieu. Raised the issue here: https://github.com/quarkusio/quarkus/issues/4031 – bmooney Sep 16 '19 at 08:59
  • It seems a bug in quarkus with restclient . https://github.com/quarkusio/quarkus/issues/4031 – murat karakas Jan 02 '20 at 11:44

2 Answers2

4

I found out when running in quarkus:dev mode the exception mapper is not invoked. It seems that this is caused by an exception mapper from quarkus that is only used in DEV mode (see https://github.com/quarkusio/quarkus/issues/7883).

I launched my code local as normal a normal java program, causing my exception handler to work as expected. Also when running the code on Openshift, my custom exception mapper is used as well.

note: I used quarkus version 1.8.3

0

You can try workaround with response filter implementation to find out if it is WebApplicationException and map response to yours.

@Provider
public class WebExceptionMapper implements ContainerResponseFilter {

    @Override
    public void filter(
            ContainerRequestContext requestContext,
            ContainerResponseContext responseContext
    ) {
        if (requestContext instanceof ResteasyReactiveContainerRequestContext) {
            var resteasyRequestContext = (ResteasyReactiveContainerRequestContext) requestContext;
            if (resteasyRequestContext.getServerRequestContext() instanceof QuarkusResteasyReactiveRequestContext) {
                var quarkusRequestContext = (QuarkusResteasyReactiveRequestContext) resteasyRequestContext
                        .getServerRequestContext();
                var throwable = quarkusRequestContext.getThrowable();
                if (throwable instanceof WebApplicationException) {
                    //map exception to your error response structure
                    var errorResponse = mapResponse((WebApplicationException) throwable);
                    quarkusRequestContext.setResult(errorResponse);
                }
            }
        }
    }

}