JAX-RS Exception Handling

by Vibrant Publishers

Introduction

An exception is a case where an unexpected outcome occurs during computation. This often disrupts the normal flow of the program. There are different mechanisms available to handle an exception. Here in this article, we are going to see some of the mechanisms that JAX-RS has implemented to handle exceptions in its API services.

JAX-RS Exceptions

A RESTful API may throw exceptions at many scenarios and its proper handling is important for the functionality of that service.

In JAX-RS exceptions are handled in two ways.

  1. By throwing a web application exception.
  2. By mapping exception using exception mapper.

 

  1. Throwing a web application exception

The WebApplicationException is a special RuntimeException class that JAX-RS has implemented in itself. By throwing a WebApplicationException, JAX-RS can abort a particular service method. This exception class can take an HTTP status code or a Response object as its constructor parameter.

Let us consider the following code snippet: 

@GET

 

@Path(“{id}”)

 

public Registration get(@PathParam(“id”) int id) {

 

        Registration registration = getRegistration(id);

 

        if (registration == null) {

 

            Response.ResponseBuilder builder = Response.status(Response.Status.NOT_FOUND);

 

            builder.type(“text/html”);

 

            builder.entity(“

 

Registration Not Found

 

“);

 

            throw new WebApplicationException(builder.build());

 

        }

 

        return registration;

 

}

 

 

 

Here if the object ‘registration’ is null, we create a response using the ResponseBuilder class. Here since we could not find any registration number we are setting the HTTP response code as 404 NOT_FOUND. This response class is then passed to WebApplicationException class which then throws this message as an exception to the client.

  1. Throwing a Not Found Exception

The above code can be made even simpler by just throwing a NotFoundException. Because this class extends the WebApplicationException. So instead of creating a response using the ResponseBuilder, we can throw this exception as shown below:

 

@GET

 

@Path(“{id}”)

 

public Registration get(@PathParam(“id”) int id) {

 

        Registration registration = getRegistration(id);

 

        if (registration == null) {

       

            throw new NotFoundException(“Registration NOT found”);

 

        }

 

        return registration;

 

}

 

 

 

  1. Mapping an exception using ExceptionMapper

JAX-RS also provides a mechanism to map generic or custom exceptions into a JAX-RS response. This is done using the ExceptionMapper interface. So the code that throws the exception will implement the ExceptionMapper interface.

Let us consider the above code snippet itself. There we were using the exceptions that already existed. Now let’s have a look at how we can use the ExceptionMapper in the same scenario.

First, we will build a custom ‘RegistrationNotFoundException’ class. 

public class RegistrationNotFoundException extends RuntimeException {

 

    public RegistrationNotFoundException(String message) {

 

       super(message);

 

    }

 

}

 

 

Now we will map this exception to HTTP status message 404 – Resource NOT_FOUND and will build a JAX-RS response. The RegistrationNotFoundMapper class will do this job. Note that it is implementing the ExceptionMapper interface. 

@Provider

 

public class RegistrationNotFoundMapper implements ExceptionMapper {

 

    public Response toResponse(RegistrationNotFoundException exception) {

 

        return Response.status(Response.Status.NOT_FOUND).

 

                entity(exception.getMessage()).

 

                type(“text/plain”).

 

                build();

 

    }

 

}

 

 

 

Here the @Provider annotation is used for automatic discovery. You don’t need to declare the exception manually. The JAX-RS runtime will automatically discover it during the provider scanning phase.

Finally, you throw the RegistrationNotFoundException.

 

@GET

 

@Path(“{id}”)

 

public Registration get(@PathParam(“id”) int id) {

 

        Registration registration = getRegistration(id);

 

        if (exam == null) {

 

            throw new RegistrationNotFoundException(“Registration is not Found”);

 

        }

 

        return registration;

 

}

 

 This will invoke RegistrationNotFoundMapper.toResponse and will send the custom response to the client.  

The mapping of exceptions in this case is explained in the below given diagram.

 

 

Exception Mapping Mechanism

Exception mapping providers map a runtime or checked exception to an instance of JAX-RS Response. If multiple exception providers are available, then one with the highest priority will be chosen.

What will happen if an exception mapper fails to map an exception and that itself throws an error? In this case, a server error with status code 500 is returned to the client as a response.

Summary

There are different exception handling mechanisms available in JAX-RS. The simple and easy choice would be to use the built-in WebApplicationException. If there is a need to use custom exceptions, then the ExceptionMapper interface can be implemented in the code.