1

I've created a custom ExceptionMapper that I wan' to call every time an exception occurs in the API to map it to a suitable response. The following is my custom exception class:

@Provider
public class ServiceExceptionMapper implements ExceptionMapper<Throwable> {
  private Logger logging = LoggerFactory.getLogger(getClass());

  @Override
  public Response toResponse(Throwable throwable) {
    log.error("There is an exception: ", throwable);


    if (throwable instanceof IllegalArgumentException) {
      return Response.status(Response.Status.BAD_REQUEST).entity(throwable.getMessage()).type    (MediaType.TEXT_PLAIN).build();
    }

    if (throwable instanceof WebApplicationException) {
      WebApplicationException we = (WebApplicationException) throwable;
      return we.getResponse();
    }
    return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(throwable.getMessage()).type(MediaType.TEXT_PLAIN).build();
   }
}

Now, in my resource class, I have a try and a catch block. If there is an exception, the catch block should catch it and invoke the custom exception mapper class. Usual way of throwing an exception is the following:

 catch (Exception e) {
    throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity("Internal Server Error").build());
}

I'm trying to call the exception mapper class in the following way:

catch (Exception e) {
    exceptionMapper.toResponse(e);
}

Where exceptionMapper is a field of the class ServiceExceptionMapper.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
Aiguo
  • 3,416
  • 7
  • 27
  • 52
  • Please clarify _how can I call my custom exception mapper class to throw the same exception?_ – cassiomolin Jan 25 '17 at 15:36
  • @CássioMazzochiMolin, I want the custom exception mapper class to take care of throwing the exceptions that occur in the API. Therefore instead of directly throwing an exception (my second code snippet) I want to call the exception mapper class and want it to throw that exception – Aiguo Jan 25 '17 at 15:49

1 Answers1

5

What are ExceptionMappers for?

But how can I call my custom exception mapper class to throw the same exception?

I want the custom exception mapper class to take care of throwing the exceptions that occur in the API. Therefore instead of directly throwing an exception (my second code snippet) I want to call the exception mapper class and want it to throw that exception.

The idea behind and ExceptionMapper is to map an Exception that has been thrown to a Response. Check the ExceptionMapper#toResponse(E) method signature and you will see it receives something that extends Throwable and must return a Response. Such method is invoked by the JAX-RS runtime.

If, for any reason, you don't want to throw exceptions directly in your resource method code, you may consider creating an utility class to do it and then you can invoke its methods to instantiate and throw the exceptions. And then the ExceptionMapper will map the exception that has been thrown to a HTTP response.

Looking up providers with JAX-RS

If you need to perform runtime look up of provider instances (ExceptionMappers are providers), you can use the Providers injectable interface. Use the @Context annotation to inject it in your resource classes:

@Context
private Providers providers;

Then you can get an ExceptionMapper for a particular class of exception:

ExceptionMapper<Throwable> exceptionMapper = providers.getExceptionMapper(Throwable.class);

Note 1: For other types that can be injected with the @Context annotation, refer to this answer.

Note 2: The Providers interface API allows you to look up the following providers:

Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • thank you for the clarification. I've updated the question, please take a look at it and let me know if I'm wrong. Thanks once again! – Aiguo Jan 25 '17 at 16:46
  • there's no any other programmatic way to get 'Providers'? I have h2k-spring bridge, and I would have the need to get 'Providers' from Spring class – Giulio Pulina Nov 24 '17 at 11:58
  • @GiulioPulina I'm not aware of other standard way to achieve it. – cassiomolin Nov 24 '17 at 12:04