1. Introduction

In this tutorial, we will learn how to apply exception handling in Spring RESTful services using ControllerAdvice annotation and ResponseEntityExceptionHandler/ResponseStatusException.

What you will learn:

  • Configure @ControllerAdvice annotation in Spring
  • Creating exception handlers using @ExceptionHandler annotation
  • Returning custom exception messages
  • Returning an exception message using ResponEntityExceptionHandler inbuilt method
  • Handling exceptions using ResponseStatusException

Note: There are several other ways that were used before Spring 3.2. We are not covering ResponseStatusExceptionHandler/ResponseStatusExceptionResolver in this tutorial.

2. Dependencies and REST APIs

We will use REST APIs we developed for ItemController in this post.

3. Using @ControllerAdvice

Introduced in Spring 3.2. it’s a better way to handle different kind of exceptions using @ExceptionHandler annotation. ResponseEntity used for type safety and provides flexibility to include HTTP headers and response status.

Let’s create a new controller advice class

@ControllerAdvice
public class ExceptionHandlingController {

    @ExceptionHandler(NumberFormatException.class)
    public ResponseEntity<ExceptionResponse> numberFormat(NumberFormatException ex, WebRequest request) {
        ExceptionResponse response = new ExceptionResponse();
        response.setErrorCode("BadRequest");
        response.setErrorMessage(ex.getMessage());
        return new ResponseEntity<ExceptionResponse>(response, HttpStatus.BAD_REQUEST);
    }

}

Above is the very simple implementation of controller advice. We have created an exception handler for handling NumberFormatException using @ExceptionHandler above the method.

We are returning a custom ExceptionResponse wrapped under ResponseEntity.

Let’s create a custom exception class and use it under controller advice.

public class ResourceNotFoundException extends RuntimeException {
    ....

    public ResourceNotFoundException(String resourceId, String message) {
        super(message);
        this.setResourceId(resourceId);
    }
}

We have created a custom exception called ResourceNotFoundException.

Now we can use it like NumberFormatException in the last example.

@ControllerAdvice
public class ExceptionHandlingController {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ExceptionResponse> resourceNotFound(ResourceNotFoundException ex) {
        ....
    }
}

Let’s place a request with item id 1 that is not available in the system.

3.1. Utilizing ResponseEntityExceptionHandler

Spring provides an inbuilt class that we can utilize in our controller advice class.

Let’s see another way of preparing an error message using Spring inbuilt features.

@ControllerAdvice
public class ExceptionHandlingController extends ResponseEntityExceptionHandler {
    
    @ExceptionHandler(BadRequestException.class)
    public ResponseEntity<Object> resourceConflict(BadRequestException ex, WebRequest request) {
        ExceptionResponse response = new ExceptionResponse();
        response.setErrorCode("BadRequest");
        response.setErrorMessage(ex.getMessage());
        return handleExceptionInternal(ex, response, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
    }
}

In the above example, we are extending ResponseEntityExceptionHandler. Now we are calling inbuilt method handleExceptionInternal for preparing the exception response message.

Let’s place a request and we will see a different format of the message returned to the client.

4. Using ResponseStatusException

ResponseStatusException introduced in Spring 5. Using this we can pass HttpStatus and an optional message as well a root cause.

Let’s create a new exception with a message and a HttpStatus.

@DeleteMapping("/deleteItem/{code}")
public Long deleteItem(@PathVariable Long code) {
    if (code < 1)
        throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Item code can't be a negative number");
    if (itemManager.getItem(code) == null)
        throw new ResourceNotFoundException("" + code, "Item not found");
    itemManager.deleteItem(code);
    return code;
}

Now let’s send a delete request with a negative item id.

5. Conclusion

In this post, we learned different ways of exception handling for Spring based RESTful APIs. We also observed that ResponseStatusException is the simple and powerful approach to use for exception handling.

The complete source can be found over on GitHub.

Exception Handling for Spring RESTful Services

Satish Pandey

I am an expert Java Spring Angular developer with 10+ years of rich and varied experience in developing end-to-end Web Applications. I maintain this blog and publish articles in my free time to help the community. Email: satish@cloudtechpro.com

Leave a Reply

avatar
1024
  Subscribe  
Notify of