An Exception is a problem that arise during the execution of a program. For Example, If there is a text field and any user entered number/digits in it, the program must not be crashed rather it should shows any error message or throw an exception. In order to handle these exceptions, spring-based frameworks came along with the @ControllerAdvice annotation.
What is @ControllerAdvice annotation?
The @ControllerAdvice annotation is a specialized form of Spring’s stereotype annotation @Component, which is used to handle global exceptions. The @ControllerAdvice annotation allows us to use the same exception handling techniques throughout the whole application.
Example:
If we have an e-commerce application and it has three different controllers, say HomeController, SearchController, and ProductController, we have written the exception handling code inside HomeController. Now, if any exceptions occur in SearchController, they are not going to be handled, as the exception handling codes are present only in HomeController. So, we need to write the exception handling code in all the three controllers, which is a time and space consuming process.
We can resolve this problem by creating a generic custom exception handling class, adding all the exception handling codes for all three controllers to this class, and annotating this class with the @ControllerAdvice annotation. It will inform the spring to handle the exception using this generic class whenever any exceptions occur.
In our previous tutorial, How to create a REST API | User API, we developed our User API, through which we can perform the following operations on a user entity: i.e., create, update, fetch, and delete. When we try to fetch user details using userId, which is not available, spring will throw our custom ResourceNotFoundException, but it is not handled properly and is not in standard format.
Steps to Global Exception handling using @ControllerAdvice
Step 1- Create GlobalExceptionHandler Class
In this step, we will create a new GlobalExceptionHandler class and annotate this class with the @ControllerAdvice annotation. The @ControllerAdvice annotation will make this class a global exception handler and scan the whole application for any exceptions. Also, as we are working with REST APIs we will user @RestControllerAdvice to get standard REST Response. For this, Go to Utils Package > Right-Click > New > Create GlobalExceptionHandler Class.
Step 2- Create Exception Handler Method
In this step, we will create custom exception handler methods in GlobalExceptionHandler class, and we need to inform Spring which method needs to be called and what the response will be when any exceptions occur.
package com.paulsofts.blogapplicationservices.utils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
//we have used return type of GenericResponse<T> class and
//this method will be called whereever we will throw
//our custom ResourceNotFoundException
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<GenericResponse<String>> resourceNotFoundExceptionHandler(ResourceNotFoundException resourceNotFoundException){
//reading message from ResourceNotFoundException class instance
String message = resourceNotFoundException.getMessage();
return new ResponseEntity<GenericResponse<String>>(
new GenericResponse<String>(message, "Not Found", "False"), HttpStatus.NOT_FOUND);
}
}
Step 3- Test Application
In this step, we will test our application. We will run our application and request the services with the userId, which is not available, and check whether the exception is getting handled globally or not.