@ControllerAdvice is a specialization of @Component that lets you define @ExceptionHandler, @InitBinder, and @ModelAttribute methods in one place. When declared in a class annotated with @ControllerAdvice, these methods apply globally, across all @RequestMapping methods in every @Controller class, instead of being limited to a single local @Controller class.
In this example we demonstrate the use of @ControllerAdvice with @ExceptionHandler to centralize exception handling for two otherwise unrelated controllers and render the result as a JSP error view.
Creating controllers
package com.logicbig.example;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ExampleController1 {
@RequestMapping("/test1")
public String handleRequest1 () throws Exception {
String msg = String.format("Test exception from class: %s",
this.getClass().getSimpleName());
throw new Exception(msg);
}
}
package com.logicbig.example;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class ExampleController2 {
@RequestMapping("/test2")
public String handleRequest2 () throws Exception {
String msg = String.format("Test exception from class: %s",
this.getClass().getSimpleName());
throw new RuntimeException(msg);
}
}
Creating a class with @ControllerAdvice
package com.logicbig.example;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@ControllerAdvice
public class MyControllerAdvice {
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleException (Exception exception, Model model) {
model.addAttribute("exception", exception);
return "exception-page";
}
}
src/main/webapp/WEB-INF/views/exception-page.jsp<%@ page language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<body>
<h3>Exception Page</h3>
<p>
status:<br/><%=response.getStatus()%>
</p>
<p>
Exception Message:<br/>${exception.message}
</p>
<p>
Exception type:<br/>${exception['class'].name}
</p>
</body>
</html>
JavaConfig class
package com.logicbig.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@EnableWebMvc
@ComponentScan
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/views/", ".jsp");
}
}
Running the example
To try examples, run embedded Jetty (configured in pom.xml of example project below):
mvn jetty:run
Output
/test1
$ curl -s "http://localhost:8080/example/test1"
<html> <body> <h3>Exception Page</h3> <p> status:<br/>500 </p> <p> Exception Message:<br/>Test exception from class: ExampleController1 </p> <p> Exception type:<br/>java.lang.Exception </p> </body> </html>
Output In Browser
/test2
$ curl -s "http://localhost:8080/example/test2"
<html> <body> <h3>Exception Page</h3> <p> status:<br/>500 </p> <p> Exception Message:<br/>Test exception from class: ExampleController2 </p> <p> Exception type:<br/>java.lang.RuntimeException </p> </body> </html>
Output In Browser
Example ProjectDependencies and Technologies Used: - spring-webmvc 7.0.6 (Spring Web MVC)
Version Compatibility: 4.2.2.RELEASE - 7.0.6 Version compatibilities of spring-webmvc with this example: Versions in green have been tested.
- jakarta.servlet-api 6.1.0 (Jakarta Servlet API documentation)
- JDK 25
- Maven 3.9.11
|