Skip to main content

Exception Handling in RESTful Web Services

Introduction

Exception Handling in RESTful webservices is very interesting as well as important topic while writing RESTful web services.
Whenever any exception occurs in our web service, by default it will show error with HTTP error code with the description which user can’t understand easily.

Why one should handle Exceptions in Restful Web services?

User should understand if any error occurred in the system and he/she should easily understand what to do next so that error will not come again as most of the error are due to wrong input given by user and if sometimes error is due to our application he should clearly know that.

How to Handle Exceptions in Restful Web services?

In RESTful web services, usually response will be in JSON format. So, we need to create response object which will give error in JSON format.
Woooooh So let’s get hand dirty.

-------------------------------------------------------------------------------------------------

//ErrorResponse.java
package com.app.exception.mapper;

public class ErrorResponse {
       private long timestamp;
       private int status;
       private String error;
       private String message;
       private String path;
      
       public String getError() {
              return error;
       }
       public void setError(String error) {
              this.error = error;
       }
       public long getTimestamp() {
              return timestamp;
       }
       public void setTimestamp(long timestamp) {
              this.timestamp = timestamp;
       }
       public int getStatus() {
              return status;
       }
       public void setStatus(int status) {
              this.status = status;
       }
       public String getMessage() {
              return message;
       }
       public void setMessage(String message) {
              this.message = message;
       }
       public String getPath() {
              return path;
       }
       public void setPath(String path) {
              this.path = path;
       }


-------------------------------------------------------------------------------------------------

In above class, we created POJO class for ErrorResponse, where we are taking current timestamp to know that when the error occurred. The status to know what the status of error is.
Message is for error description and path to know about at what RESTful webservice the error came as we will develop lots of RESTful webservices. So, to understand where exactly error and it will easy to debug.

Now we will create ApplicationExceptionMapper to inject the error occurred in ErrorResponse object.
 -------------------------------------------------------------------------------------------------
//ApplicationExceptionMapper.java

package com.app.exception.mapper;

import java.util.Date;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang3.StringUtils;

public class ApplicationExceptionMapper {
       @Context
       private UriInfo uriInfo;
      
       protected Response getErrorResponse(Exception e, Status statusCode, String error) {       
              final ErrorResponse errorResponse = new ErrorResponse();        
              errorResponse.setStatus(statusCode.getStatusCode());
              errorResponse.setPath(uriInfo.getPath());
              errorResponse.setTimestamp(new Date().getTime());
              errorResponse.setError(error);
              errorResponse.setMessage(null == e ? StringUtils.EMPTY : e.getMessage());
              return Response.status(statusCode).entity(errorResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
       }

       protected Response getErrorResponse(Status statusCode, String error) {
              final ErrorResponse errorResponse = new ErrorResponse();
              errorResponse.setStatus(statusCode.getStatusCode());
              errorResponse.setPath(uriInfo.getPath());
              errorResponse.setTimestamp(new Date().getTime());
              errorResponse.setError(error);
              errorResponse.setMessage("A problem has occurred please try again later");
              return Response.status(statusCode). entity(errorResponse).type(MediaType.APPLICATION_JSON_TYPE).build();
       }
}

 -------------------------------------------------------------------------------------------------
Now we will make GenericExceptionMapper to map exception which did not match with any exceptions we handled and give error in proper format.

-------------------------------------------------------------------------------------------------
//GenericExceptionMapper.java
package com.app.exception.mapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;

public class GenericExceptionMapper extends ApplicationExceptionMapper implements ExceptionMapper<RuntimeException> {
       private static final Logger logger = LoggerFactory.getLogger(GenericExceptionMapper.class);

       @Override
       public Response toResponse(final RuntimeException e) {
              logger.error("A RuntimeException occurred", e);
              return getErrorResponse(Status.INTERNAL_SERVER_ERROR, "Internal Server Error");
       }
}
-------------------------------------------------------------------------------------------------
We need to create WebApplicationExceptionMapper to catch WebApplicationException
-------------------------------------------------------------------------------------------------
//WebApplicationExceptionMapper.java

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/ * *
*
* Standard handler for any javax.ws.rs.WebApplicationException
*
*/

public class WebApplicationExceptionMapper extends ApplicationExceptionMapper implements ExceptionMapper<WebApplicationException> {  
private static final Logger logger = LoggerFactory.getLogger(WebApplicationExceptionMapper.class);  

@Override
public Response toResponse(final WebApplicationException wae){

          logger.info("toResponse() - Returning a web exception to caller with status={}, message=\"{}\"", wae.getResponse().getStatusInfo().getStatusCode(), wae.getMessage(), wae);  
          return getErrorResponse(wae, Status.fromStatusCode(wae.getResponse().getStatus()), wae.getMessage());
    }
}


-------------------------------------------------------------------------------------------------
Now there are some standard HTTP status code which used in web API. Here are some examples-
500 – InternalServerError
400 – BadRequest(IllegalArgumentException)
404 – Not Found
204 – No Content
201 – Resource created used for POST request
200 – OK    etc.

more Http-status code information: https://httpstatuses.com/

To Handle 400 IllegalArgumentException, we need to create IllegalArgumentExceptionMapper

-------------------------------------------------------------------------------------------------
//IllegalArgumentExceptionMapper.java
package com.app.exception.mapper;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class IllegalArgumentExceptionMapper extends ApplicationExceptionMapper implements ExceptionMapper<IllegalArgumentException> {

    private static final Logger logger = LoggerFactory.getLogger(IllegalArgumentExceptionMapper.class);
   
    @Override
    public Response toResponse(IllegalArgumentException exception) {
       logger.info("Mapping IllegalArgumentException to {}, with message {}", Status.BAD_REQUEST.getStatusCode(), null == exception ? StringUtils.EMPTY : exception.getMessage());
        return getErrorResponse(exception, Status.BAD_REQUEST, "Bad Request");       
    }
}

-------------------------------------------------------------------------------------------------

Same like IllegalArgumentExceptionMapper, you can create mapper for any HTTP status code.

Thank you …!!!

Comments

Popular posts from this blog

Restful API for Beginners

Introduction: Everyone is saying Rest API. Sometimes people say  only API to rest apis.RESTful API is for accessing blah blah service or to do blah blah functionality. In corporate world, fresher get confused when seniors give them task to create new api to call blah blah service or to do blah blah functionality. So what is this REST API? REST (REpresentational State Transfer) is an architectural style, and an approach to communications.Using this REST whatever functionality we create known as REST API. We can implement  rest-api using various providers but usually people use Jersey and Spring . As per my choice personally I would like to use jersey which keep code neat and clean. Rest follows client-server architecture with Front Controller Design Pattern. It completely depends on http protocol .REST implementation is very easy and run in  less memory compared to SOAP. Rest Support following parameter techniques to pass input for our web service...

Exception Propagation and throw-throws keyword

Exception Propagation: Sending exception from one method to another method is called exception propagation Here propagation is nothing but sending. So guys what is the situation when we are going to implement this propagation concept? Answer to this question is when we throw an exception, if it is not caught in that method it is propagated to another method and interesting thing is that we don’t need to do anything in this process we just need to throw an exception that’s it. Rule: If the propagated exception is checked exception then not only current method developer but also method’s caller method developer should caught or report that checked exception else it leads to same compiler exception….CE: Unreported Exception So according to that basic rule is “If checked exception is raised the method either directly by using throw keyword or indirectly by a method call it must be caught or reported. void m1() throws ClassNotFoundException{ ...

User Defined Exception Handling

Introduction: To develop the project, we must create our own Exception class, as Sun microsystem has not given any exception class some requirements which are not in common. So, what is User defined exception is? Exception class defined by Developer is called as User Defined Exception or Custom exception Steps to create User Defined Exception: Write a class that extends java.lang.Exception. In User defined class, define minimum 2 constructors. No-argument constructor String parameter with logic “super(message)” to create exception object with message.  No need to define any method, why because exception class is not meant for developing business logic , instead it is used for terminating method logic execution by throwing it’s object. ------------------------------------------------------------------------------------------------------------ package com.app.exceptions; /**  *  * @author Shashank Mungantiwar  * ...