Spring Global Exception Handling Using @ControllerAdvice Annotation

spring-exception-handling For several reasons, you may want a global solution to handle exceptions thrown by controllers across the whole application. Spring provides a mechanism that enables such functionality using @ControllerAdvice annotation.

Overview

  • We will build a simple Spring Boot application which includes three classes:

spring-boot-exception

  • Controller.java : Simple controller responding to GET requests mapped to /ok & /exception.
  • ControllerAdvisor.java: A class annotated with @ControllerAdvice to handle exceptions.
  • App.java: Run the application

Dependencies

  • Spring Boot
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.4.2</version>
</parent>
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
</dependencies>

Complete Maven dependencies is included in pom.xml

Spring MVC Controller

We will build a simple controller which has two services:

  • First service ok() returns OK
  • The second service exception() throws an Exception.

Controller.java

@RestController
public class Controller {


	 @RequestMapping("/ok")
	 public @ResponseBody String ok() throws Exception {
	  	return "OK";
	 }

	 @RequestMapping("/exception")
	 public @ResponseBody String exception() throws Exception {
	  	throw new Exception("Error");
	 }
}
  • If we call /exception, “before implementing @ControllerAdvice” we will see following message

spring-boot-exception-before

  • Also, notice that the HTTP status code is 500 Internal Server Error.

@ControllerAdvice

  • We can handle the previous exception using @ControllerAdvice by defining a new class annotated with this annotation.
  • Methods of this class can be annotated by @ExceptionHandler which defines a single or a list of exceptions types to be handled.
  • @ResponseStatus is used to override the response status code to be returned by annotated methods.
@ControllerAdvice
public class ControllerAdvisor {


	@ExceptionHandler(Exception.class)
	@ResponseStatus(HttpStatus.BAD_REQUEST)

	public @ResponseBody String generalException(final Exception exception,
			final HttpServletRequest request) {

		return exception.getMessage()+" while calling: "+request.getRequestURI();

	}
}
  • Now, when calling the /exception service, @ControllerAdvice class will handle the thrown exception and will set the status code to 400 Bad Request.

spring-boot-exception-before

Source Code @ GitHub