ExceptionMapper for WebApplicationExceptions thrown with entity?
Asked Answered
W

2

10

In our (legacy) codebase, we're throwing WebApplicationExceptions in different ways. In an attempt to make some order in how we're handling exceptions - I wanted to create an ExceptionMapper for these WAEs (and others).

I realized, however, that Jersey's ExceptionMapper only maps WAE which weren't thrown with an entity.

For example:

throw new WebApplicationException(Response.status(500).build());

This exception is caught by the ExceptionMapper.

throw new WebApplicationException(Response.status(500).entity(WsResourceUtils.createWSResourceRestError(500, "bla")).build());

This exception is NOT caught by the ExceptionMapper.

Both are thrown from the same point in code.

This is my ExceptionMapper:

@Provider
public class GeneralExceptionMapper implements ExceptionMapper<Throwable> {

    private static final Logger logger = LoggerFactory.getLogger(GeneralExceptionMapper.class);

    @Override
    public Response toResponse(Throwable e) {
        logger.error("Caught a WAE", e);
...
}

Is it possible to create an ExceptionMapper which will catch WebApplicationExceptions even if their response is already built with an entity?

We're using Jersey 1.17.

Thanks.

Wendling answered 2/4, 2015 at 13:20 Comment(2)
2 years later, this is still an issue with Jersey 2.26Patrol
Sorry to resurrect a thread that's nearly three years old, but RestEasy 3.0.11 also exhibits this. If I create my WAE without an entity, my mapper gets called. If I create it with the entity, my mapper never sees it. Perhaps this is defined in JAX-RS?Faden
T
-1

please consider looking at the code in GIST :

https://gist.github.com/jeorfevre/9fb2c447a01bcc724998

  1. Register a Mapper that of MagicException that contains Response
  2. Define Exception that contain response
  3. Throw this exception
Techno answered 8/5, 2015 at 13:29 Comment(5)
1. This solution requires me to change every place I'm throwing WebApplicationExceptions, to throw MagicException instead. 2. You're not handling the main issue - MagicException still has an entity set in it, and so it will still not be caught by the mapper.Wendling
How is that different than what I've done? I already have an exception mapper, but it doesn't catch WAE which are already thrown with an entity.Wendling
since you do not see, I'll modify my code another time.Techno
This solution works with a little tweak - WebApplicationException.getResponse is a final method and so can't be overrided. I need to create a separate getter for the response object, and only use that one to extract the response in the mapper. Unfortunately this forces me to use reflection to figure out if the object is of the inherited type, but I guess that's better than nothing. Do you have any other idea on how to handle that issue?Wendling
There is many ways to manage such a behaviour. But only reflection is making a nice, clean, easy to maintain code. Enjoy :)Techno
A
0

This behaviour is describe in the JAX-RS specification and it's still true in version 3.0 :

Instances of WebApplicationException and its subclasses MUST be mapped to a response as follows. If the response property of the exception does not contain an entity and an exception mapping provider (see Exception Mapping Providers) is available for WebApplicationException or the corresponding subclass, an implementation MUST use the provider to create a new Response instance, otherwise the response property is used directly. The resulting Response instance is then processed according to Return Type.

Source : https://jakarta.ee/specifications/restful-ws/3.0/jakarta-restful-ws-spec-3.0.html#method_exc

I don't know why and I think it's not ideal but it's definitely not a bug.

Aarhus answered 22/12, 2022 at 8:39 Comment(0)
T
-1

please consider looking at the code in GIST :

https://gist.github.com/jeorfevre/9fb2c447a01bcc724998

  1. Register a Mapper that of MagicException that contains Response
  2. Define Exception that contain response
  3. Throw this exception
Techno answered 8/5, 2015 at 13:29 Comment(5)
1. This solution requires me to change every place I'm throwing WebApplicationExceptions, to throw MagicException instead. 2. You're not handling the main issue - MagicException still has an entity set in it, and so it will still not be caught by the mapper.Wendling
How is that different than what I've done? I already have an exception mapper, but it doesn't catch WAE which are already thrown with an entity.Wendling
since you do not see, I'll modify my code another time.Techno
This solution works with a little tweak - WebApplicationException.getResponse is a final method and so can't be overrided. I need to create a separate getter for the response object, and only use that one to extract the response in the mapper. Unfortunately this forces me to use reflection to figure out if the object is of the inherited type, but I guess that's better than nothing. Do you have any other idea on how to handle that issue?Wendling
There is many ways to manage such a behaviour. But only reflection is making a nice, clean, easy to maintain code. Enjoy :)Techno

© 2022 - 2024 — McMap. All rights reserved.