Reputation:
I have a REST service with a method anotated with @Produces("application/pdf")
.
If an exception occurres on server side, our logic throws custom exception which extends RuntimeException
and I have:
throw new CustomerException(new CustomProblem("something wrong"));
What is a best way to return something to the client, who in this case see:
Status: 500
Body: No message body writer has been found for response class CustomProblem.
Upvotes: 0
Views: 518
Reputation: 131127
Previously, I answered a similar question here.
Basically, you can adopt one of the following approaches to handle your exceptions (extracted from Jersey documentation but also applies to RESTEasy or other JAX-RS 2.0 implementations):
WebApplicationException
JAX-RS allows to define direct mapping of Java exceptions to HTTP error responses. By extending WebApplicationException
, you can create application specific exceptions that build a HTTP response with the status code and an optional message as the body of the response.
The following exception builds a HTTP response with the 404
status code:
public class CustomerNotFoundException extends WebApplicationException {
/**
* Create a HTTP 404 (Not Found) exception.
*/
public CustomerNotFoundException() {
super(Responses.notFound().build());
}
/**
* Create a HTTP 404 (Not Found) exception.
* @param message the String that is the entity of the 404 response.
*/
public CustomerNotFoundException(String message) {
super(Response.status(Responses.NOT_FOUND).
entity(message).type("text/plain").build());
}
}
WebApplicationException
is a RuntimeException
and doesn't need to the wrapped in a try
-catch
block or be declared in a throws
clause:
@Path("customers/{customerId}")
public Customer findCustomer(@PathParam("customerId") Long customerId) {
Customer customer = customerService.find(customerId);
if (customer == null) {
throw new CustomerNotFoundException("Customer not found with ID " + customerId);
}
return customer;
}
ExceptionMapper
sIn other cases it may not be appropriate to throw instances of WebApplicationException
, or classes that extend WebApplicationException
, and instead it may be preferable to map an existing exception to a response.
For such cases it is possible to use a custom exception mapping provider. The provider must implement the ExceptionMapper<E extends Throwable>
interface. For example, the following maps the JAP EntityNotFoundException
to a HTTP 404
response:
@Provider
public class EntityNotFoundExceptionMapper
implements ExceptionMapper<EntityNotFoundException> {
@Override
public Response toResponse(EntityNotFoundException ex) {
return Response.status(404).entity(ex.getMessage()).type("text/plain").build();
}
}
When an EntityNotFoundException
is thrown, the toResponse(E)
method of the EntityNotFoundExceptionMapper
instance will be invoked.
The @Provider
annotation declares that the class is of interest to the JAX-RS runtime. Such class may be added to the set of classes of the Application
instance that is configured.
Upvotes: 2
Reputation: 1615
Implement https://docs.oracle.com/javaee/6/api/javax/ws/rs/ext/ExceptionMapper.html and put the annotation @Provider to that. Override the toResponse() method and return a Response which is JSON or something meaningful. You can also use @Context to obtain the header passed in the request.
Upvotes: 0