user1308908
user1308908

Reputation:

Handling errors in REST webservices with Java

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

Answers (2)

cassiomolin
cassiomolin

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):

Extending 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;
}

Creating ExceptionMappers

In 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

Neeraj Krishna
Neeraj Krishna

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

Related Questions