A typical way to deal with exceptions in REST service is to define custom exception types (typically from RuntimeException
) and then implement a mapper class to produce HTTP codes, for example:
public class MyExceptionMapper implements ExceptionMapper<MyException> {
@Override
public Response toResponse(MyExceptionex) {
return Response.status(400).entity("bad request")
.type(MediaType.APPLICATION_JSON).build();
}
}
Now, I have 2 questions:
Throwable
in order to produce an HTTP 500, wouldn't it catch my own exceptions again? Or can an order be defined in which mappers work?EJBException
or some Transaction...Exception
wrapping my own one?Just as Paul Samsotha writes in the comment, the JAX-RS server runtime is supposed to pick the most specific exception mapper. Or to quote the JAX-RS specs (for JEE7/version 2.0):
3.3.4 Exceptions
[...]
- If an exception mapping provider (see Section 4.4) is available for the exception or one of its superclasses, an implementation MUST use the provider whose generic type is the nearest superclass of the exception to create a Response instance that is then processed according to Section 3.3.3.[...]
So I guess you can use an exception mapper for Throwable
- its signature verifies it anyway:
public interface ExceptionMapper<E extends Throwable> {...}
The EJB container will wrap the exception, if it needs to be wrapped. Not all exceptions thrown by EJBs are required to be wrapped. The EJB spec (v3.1) makes the distinction between application exceptions (annotated with javax.ejb.ApplicationException
) and "all other exceptions" (see section 14.3).
So make the exception @ApplicationException
and provide a mapper for it. But if you still want to respond based on the wrapped exception:
You cannot directly select a mapper based on the wrapped exception. But you can create an exception mapper for the wrapper exception that unwraps it and selects an appropriate mapper for the wrapped exception based on the Providers
context (see JAX-RS 2.0 section 9.2.6 and the javax.ws.rs.ext.Providers
Javadocs). An example, untested code for a hypothetical MyWrapperException
would be:
@Provider
public class MyWrapperExceptionMapper implements ExceptionMapper<MyWrapperException> {
@Context
private Providers providers;
public Response toResponse(MyWrapperException e) {
Throwable t = e.getCause();
ExceptionMapper mapper = providers.getExceptionMapper(t.getClass());
if( mapper != null ) {
return mapper.toResponse(t);
}
else {
// custom handling...
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With