RESTful Java JAX RS Exception Handling
Errors can be reported to a client
- either by creating and returning the appropriate
Response
object; - or by throwing an
Exception
.
There are 3 ways of handling thrown exceptions:
- thrown exceptions are handled by the JAX-RS runtime (if there is an exception mapper registered);
- if the thrown exception is not handled by a mapper (
javax.ws.rs.ext.ExceptionMapper
), it is propagated and handled by the container JAX-RS is running within; - a
javax.ws.rs.WebApplicationException
can be thrown by application code and automatically processed by JAX-RS without having to write an explicit mapper.
Exception Mapping
Relying on the underlying servlet container to handle the exception doesn’t give much flexibility. Catching and then wrapping all these exceptions within WebApplicationException would become quite tedious. Alternatively, you can implement and register instances of ExceptionMapper. These objects know how to map a thrown application exception to a Response object:
public interface ExceptionMapper<E extends Throwable> {
Response toResponse(E exception);
}
For example:
@Provider
public class NullPointerExceptionMapper
implements ExceptionMapper<NullPointerException> {
public Response toResponse(NullPointerException e) {
return Response.status(Response.Status.NOT_FOUND).build();
}
}
The implementation must be annotated with the @Provider
annotation (to tell the JAX-RS runtime that it is a component).
JAX-RS supports exception inheritance as well. When an exception is thrown, JAX-RS will first try to find an ExceptionMapper for that exception’s type. If it cannot find one, it will look for a mapper that can handle the exception’s superclass. It will continue this process until there are no more superclasses to match against.
javax.ws.rs.WebApplicationException
JAX-RS has a built-in unchecked exception that applications can throw. This exception is preinitialized with either a Response or a particular status code:
public class WebApplicationException extends RuntimeException {
public WebApplicationException() {...}
public WebApplicationException(Response response) {...}
public WebApplicationException(int status) {...}
public WebApplicationException(Response.Status status) {...}
public WebApplicationException(Throwable cause) {...}
public WebApplicationException(Throwable cause, Response response) {...}
public WebApplicationException(Throwable cause, int status) {...}
public WebApplicationException(Throwable cause, Response.Status status) {...}
public Response getResponse() {...}
}
When JAX-RS sees that a WebApplicationException has been thrown by application code, it catches the exception and calls its getResponse()
method to obtain a Response to send back to the client. If the application has initialized the WebApplicationException with a status code or Response object, that code or Response will be used to create the actual HTTP response. Otherwise, the WebApplicationException will return a status code of 500 Internal Server Error
to the client.
For example:
@Path("/test")
public class TestResource {
@GET
@Path("/something")
@Produces("application/xml")
public Customer getCustomer(@QueryParam("id") int id) {
Something something = findSomething(id);
if (something == null) {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
return something;
}
}
Exception Hierarchy
JAX-RS 2.0 has added a nice exception hierarchy for various HTTP error conditions. So, instead of creating an instance of WebApplicationException and initializing it with a specific status code, you can use one of these exceptions instead.
Exception | Status code | Description |
---|---|---|
BadRequestException | 400 | Malformed message |
NotAuthorizedException | 401 | Authentication failure |
ForbiddenException | 403 | Not permitted to access |
NotFoundException | 404 | Couldn’t find resource |
NotAllowedException | 405 | HTTP method not supported |
NotAcceptableException | 406 | Client media type requested not supported |
NotSupportedException | 415 | Client posted media type not supported |
InternalServerErrorException | 500 | General server error |
ServiceUnavailableException | 503 | Server is temporarily unavailable or busy |
Resources
Categories & Tags
Share