Spring Boot @ExceptionHandler tutorial shows how to handle exceptions with Spring @ExceptionHandler.
last modified July 16, 2023
Spring Boot @ExceptionHandler tutorial shows how to handle exceptions with Spring @ExceptionHandler.
Spring is a popular Java application framework and Spring Boot is an evolution of Spring that helps create stand-alone, production-grade Spring based applications easily.
@ExceptionHandler is an annotation for handling exceptions in specific handler classes or handler methods. In Servlet environments, we can combine the @ExceptionHandler annotation with @ResponseStatus to define the response status for the HTTP response.
In the following application, we demonstrate the usage of the @ExceptionHandler. A HTML link in the home page calls a controller’s method, which either returns data or throws an exception.
build.gradle … src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── Application.java │ │ ├── controller │ │ │ └── MyController.java │ │ ├── exception │ │ │ └── MyDataException.java │ │ └── service │ │ ├── IDataService.java │ │ └── MyDataService.java │ └── resources │ ├── static │ │ ├── index.html │ │ └── showError.html │ └── templates │ └── showData.ftlh └── test ├── java └── resources
This is the project structure of the Spring application.
build.gradle
plugins { id ‘org.springframework.boot’ version ‘3.1.1’ id ‘io.spring.dependency-management’ version ‘1.1.0’ id ‘java’ }
group = ‘com.zetcode’ version = ‘0.0.1-SNAPSHOT’ sourceCompatibility = ‘17’
repositories { mavenCentral() }
dependencies { implementation ‘org.springframework.boot:spring-boot-starter-web’ implementation ‘org.springframework.boot:spring-boot-starter-freemarker’ }
This is the Gradle build file. The spring-boot-starter-freemarker is a dependency for Freemarker template engine.
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import com.zetcode.exception.MyDataException; import com.zetcode.service.IDataService; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView;
import java.util.HashMap; import java.util.Map;
@Controller public class MyController {
private final IDataService dataService;
public MyController(IDataService dataService) {
this.dataService = dataService;
}
@RequestMapping(value = "/getData")
public ModelAndView getData() {
var data = dataService.findAll();
Map<String, Object> params = new HashMap<>();
params.put("values", data);
return new ModelAndView("showData", params);
}
@ExceptionHandler(MyDataException.class)
public String handleError(MyDataException e) {
return "redirect:/showError.html";
}
}
The MyController’s getData method calls a service method and stores the retrieved data into a list. The data is sent to the showData view. In case of a MyDataException, the controller redirects to an error page.
@ExceptionHandler(MyDataException.class) public String handleError(MyDataException e) {
return "redirect:/showError.html";
}
The handleError is decorated with @ExceptionHandler. The handler is activated for the MyDataException. In the body of the method, we redirect to the showError.html page.
com/zetcode/exception/MyDataException.java
package com.zetcode.exception;
public class MyDataException extends RuntimeException {
public MyDataException(String message) {
super(message);
}
}
We define a custom MyDataException.
com/zetcode/service/IDataService.java
package com.zetcode.service;
import java.util.List;
public interface IDataService {
List<String> findAll();
}
IDataService contains the contract method.
com/zetcode/service/MyDataService.java
package com.zetcode.service;
import com.zetcode.exception.MyDataException; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.springframework.stereotype.Service;
@Service public class MyDataService implements IDataService {
@Override
public List<String> findAll() {
var r = new Random();
if (r.nextBoolean()) {
throw new MyDataException("Failed to retrieve data");
}
var data = new ArrayList<String>();
data.add("yellow moon");
data.add("brisk pace");
data.add("empty bottle");
data.add("beautiful weather");
return data;
}
}
MyDataService implements IDataService’s findAll method. The method either returns data or throws a MyDataException.
var r = new Random();
if (r.nextBoolean()) {
throw new MyDataException("Failed to retrieve data");
}
The findAll method randomly throws MyDataException. The exception is then handled in the controller.
var data = new ArrayList<>();
data.add(“yellow moon”); data.add(“brisk pace”); data.add(“empty bottle”); data.add(“beautiful weather”);
return data;
When there is no exception, we return a list of strings.
resources/static/index.html
<!DOCTYPE html> <html> <head> <title>Home page</title> <meta charset=“UTF-8”> <meta name=“viewport” content=“width=device-width, initial-scale=1.0”> </head> <body> <a href="/getData">Get data</a> </body> </html>
This is the home page. It contains a link that calls our controller method to fetch some data.
resources/static/showError.html
<!DOCTYPE html> <html> <head> <title>Error</title> <meta charset=“UTF-8”> <meta name=“viewport” content=“width=device-width, initial-scale=1.0”> </head> <body> <p>Failed to retrieve data</p> </body> </html>
This is an error page. It is shown when MyDataException is thrown.
resources/templates/showData.ftlh
<!DOCTYPE html> <html> <head> <title>Data</title> <meta charset=“UTF-8”> <meta name=“viewport” content=“width=device-width, initial-scale=1.0”> </head>
<body>
<h2>Data</h2>
<ul>
<#list values as val>
<li><td>${val}</td></li>
</#list>
</ul>
</body>
</html>
The showData.ftlh is a Freemarker template file which shows all retrieved data in an HTML list.
com/zetcode/Application.java
package com.zetcode;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application is the entry point which bootstraps Spring Boot application.
In this article we have shown how to handle exceptions in a Spring application with @ExceptionHandler.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.