5

I have a resource:

@GET
@Path("/print-order")
@Produces("application/pdf")
public byte[] printOrder(@QueryParam("id") Long orderId) {
    return ...;
}

...which can throw an error that is relevant to the user and must be displayed as a HTML page. So I implemented an ExceptionMapper but I don't know how to get the value of @Produces("application/pdf") annotation of the called resource.

@Provider
public class CustomExceptionMapper implements ExceptionMapper<CustomException> {
    @Override
    public Response toResponse(CustomException exception) {
        if (contentType = "application/pdf")
            ... html respone
        else
            ... entity response
    }
}

I'm using JAX-RS 1.x (jsr311) with Jersy 1.12 implementation but would love to have implementation independent solution.

x80486
  • 6,627
  • 5
  • 52
  • 111
Sašo5
  • 61
  • 1
  • 6

1 Answers1

10

You can inject different context objects into the ExceptionMapper to get more info on the request it handles. It's convenient to determine what content type the client expects based on HTTP's Accept header (learn more here).

Below is the example on how you can make ExceptionMapper to respond with different formats based on Accept header specified (or not specified) by your APIs client.

@Provider
public class CustomExceptionMapper implements ExceptionMapper<CustomException> {

   // Inject headers of the request being processed
   @Context
   private HttpHeaders headers;

   // or even all the request details
   @Context
   private HttpServletRequest request;

   @Override
   public Response toResponse(CustomException exception) {
      List<MediaType> acceptedTypes = headers.getAcceptableMediaTypes();
      if (acceptedTypes.contains(MediaType.APPLICATION_JSON)) {
         // respond with entity
      } else {
         // respond with HTML
      }
   }
}

You initial idea can be implemented, though. You can inject HttpServletRequest in your resource class and use setAttribute() method to store application/pdf string within the context of current request. It can be later obtained in ExceptionMapper using getAttribute() method. But I wouldn't recommend to do so unless absolutely necessary. It introduces not so obvious dependencies between components of your code.

Aleksei Budiak
  • 871
  • 5
  • 16
  • Thank you for your detailed response, but this is not what I was asking. I do not have accept headers because it is not a get request but a new window link. I already have a temp fix base on the resource path, so the suggested setAttribute would be just more work. – Sašo5 Sep 07 '17 at 17:09
  • FWIW this answer was very useful to me, having found this question from a web search trying to find an answer to the very question that this answer does answer! So, thanks! I'm not sure if that makes it appropriate to upvote it or not... Maybe I should post this question and you should repost your answer to that. – EricS Jan 24 '19 at 21:42
  • Hi @EricS, glad it helped you! My answers solves the problem indicated in the original question, so upvoting would be appropriate (despite the author of question was expecting some other kind of solution). – Aleksei Budiak Jan 31 '19 at 13:04
  • @Aleksei Budiak: the OP said you didn't answer what he asked and you didn't dispute his comment. I tend to agree because he asked how to get the value of his method's produces annotation not the accept headers. – EricS Jan 31 '19 at 17:43