AdBlock Detected

It looks like you're using an ad-blocker!

Our team work realy hard to produce quality content on this website and we noticed you have ad-blocking enabled. Advertisements and advertising enable us to continue working and provide high-quality content.

REST error handling with Spring Boot

In this new Refactorizando entry, we will see how we can implement REST error handling with Spring Boot.

Spring has introduced improvements in the treatment and management of errors throughout different versions.From using @ExceptionHandler or HandlerExceptionResolver in older versions to the introduction of @ControllerAdvice and the use of ResponseStatusException starting from Spring 5.

Using @ExceptionHandler

The use of @ExceptionHandler is one of the oldest ways to handle errors in Spring. We will use this annotation at the method level within the controller.


This annotation has a main problem: it is not very reusable; it triggers error control only in that method.

public class CarController{
    
    //...
    @ExceptionHandler({ ColorCarException.class, WheelCarException.class })
    public void handleException() {
        //
    }
}

Using HandlerExceptionResolver for REST error handling with Spring Boot

Unlike @ExceptionHandler, the use of HandlerExceptionResolver allows us to manage errors for our entire application. The functionality of @ExceptionHandler is based on this improvement.

This enhancement was introduced in Spring version 3 and is active by default in the DispatcherServlet.

HandlerExceptionResolver has different implementations such as ExceptionHandlerExceptionResolver or DefaultHandlerExceptionResolver, which can handle and return a series of default Spring errors, such as 4XX and 5XX errors. This error management returns only the error code without anything in the body, unless it is done through a ModelAndView.

On the other hand, we widely use ResponseStatusExceptionResolver because of its simplicity in returning status codes in responses.For example:

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class LocationNotFoundException extends RuntimeException {
    public MyResourceNotFoundException() {
        super();
    }
    public LocationNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
    public LocationNotFoundException(String message) {
        super(message);
    }
    public LocationNotFoundException(Throwable cause) {
        super(cause);
    }
}

Although this solution is clean and practical, we cannot modify the body to add a custom object, and we have to add the @ResponseStatus to each exception.

To resolve the issue of adding information to the body, the HandlerExceptionResolver was introduced. This class allows us to return status code exceptions and also return a body. Let’s see an example:





@Component
@Slf4j
public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver {

    @Override
    protected ModelAndView doResolveException(
      HttpServletRequest request, 
      HttpServletResponse response, 
      Object handler, 
      Exception ex) {
        try {
            if (ex instanceof IllegalArgumentException) {
                return handleIllegalArgument(
                  (IllegalArgumentException) ex, response, handler);
            }
            ...
        } catch (Exception handlerException) {
            logger.warn("Handling of [" + ex.getClass().getName() + "] 
              resulted in Exception", handlerException);
        }
        return null;
    }

    private ModelAndView 
      handleIllegalArgument(IllegalArgumentException ex, HttpServletResponse response) 
      throws IOException {
        response.sendError(HttpServletResponse.SC_CONFLICT);
        String accept = request.getHeader(HttpHeaders.ACCEPT);
        ...
        return new ModelAndView();
    }
}

Although these improvements were introduced in Spring 3 and were very important for error and exception handling at that time, undoubtedly, the greatest contribution of Spring 3.2 was the introduction of @ControllerAdvice.

REST error handling with @ControllerAdvice

Undoubtedly, this is one of the best ways to handle REST errors in Spring Boot. It adds the functionality of @ExceptionHandler, with which we can capture the desired exception and have centralized control over the exceptions in our application through a single class.

Additionally, we can add information and manage the response body and handle different exceptions with the @ExceptionHandler annotation in a single method. Let’s see an example:

@ControllerAdvice
public class RestResponseEntityExceptionHandler 
  extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value 
      = { IllegalArgumentException.class, IllegalStateException.class })
    public ResponseEntity<Object> handleConflict(
      RuntimeException ex, WebRequest request) {
        String bodyOfResponse = "Illegal argument exception error";
        return handleExceptionInternal(ex, bodyOfResponse, 
          new HttpHeaders(), HttpStatus.CONFLICT, request);
    }
  @ExceptionHandler(CarException.class)
  public ResponseEntity<Object> CarException(final CarException e) {
            String bodyOfResponse = "Car exception";
        return handleExceptionInternal(ex, bodyOfResponse, 
          new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
  }
}

Handling errors in Spring Boot with ResponseStatusException

Spring introduced this newest way of handling errors in Spring 5. Using it anywhere in the code makes it particularly convenient, but I consider the use of @ControllerAdvice much cleaner. However, you can combine both approaches and use this solution locally.

@GetMapping(value = "/{id}")
public Car findById(@PathVariable("id") Long id, HttpServletResponse response) {
    try {
       Car carById = RestPreconditions.checkFound(carRepository.findOne(id));

        eventPublisher.publishEvent(new SingleResourceRetrievedEvent(this, response));
        return carById;
     }
    catch (CarNotFoundException ex) {
         throw new ResponseStatusException(
           HttpStatus.NOT_FOUND, "Car not found", exc);
    }
}

Conclusion

In this entry, we have seen different ways to perform REST error handling with Spring Boot in a simple and easy way. Managing and returning the status code as well as error information is essential in applications and for good architecture.

Leave a Reply

Your email address will not be published. Required fields are marked *