Table of contents
1.
Introduction
2.
Initial Setup
3.
Create a Spring Boot Project
3.1.
Set Up Your Development Environment
3.2.
Generate the Application Structure
3.3.
Run the Spring Boot Application
4.
Example of Spring boot application class 
5.
Spring Boot Error Handler
6.
Centralized Exception Handling with @ControllerAdvice
7.
Key Points
8.
Handling Exceptions
8.1.
Custom Exception Handling in Controllers
8.2.
Key Concepts
8.3.
Example of a global exception handler class
8.4.
Overriding Exceptions Handled in ResponseEntityExceptionHandler:
8.5.
@ControllerAdvice
9.
Implementing Custom Exceptions:
10.
Advantages of Custom Exceptions
11.
The Importance of Spring Boot Exception Handling:
12.
Frequently Asked Questions
12.1.
What is the difference between @ControllerAdvice & @ExceptionHandler?
12.2.
Can I create custom exceptions for any type of error?
12.3.
How does overriding methods in ResponseEntityExceptionHandler improve error handling?
13.
Conclusion
Last Updated: Aug 13, 2025
Medium

Exception Handling in Spring Boot

Author Rahul Singh
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Exception handling is an important concept in programming that deals with managing errors & unexpected situations that may occur during the execution of a program. In Spring Boot, exception handling plays a crucial role in building robust & reliable applications. It allows developers to gracefully handle errors, provide meaningful feedback to users, & maintain the stability of the application. 

Exception Handling in Spring Boot

In this article, we will discuss exception handling in Spring Boot, covering topics such as setting up error handlers, handling exceptions, overriding default exception handling, implementing custom exceptions, & understanding the importance of proper exception handling in Spring Boot applications.

Initial Setup

To get started with exception handling in Spring Boot, we need to set up our project with the necessary dependencies. Spring Boot provides a convenient way to handle exceptions out of the box, but we can also customize the behavior to suit our specific needs.

Create a Spring Boot Project

Use Spring Initializr (start.spring.io) to generate a project. Choose your preferred dependencies, such as Spring Web and Thymeleaf for web applications.

Set Up Your Development Environment

Ensure you have Java and Maven or Gradle installed on your machine. These tools will help you build and manage your project.

Generate the Application Structure

After downloading and unzipping your project, open it in an IDE like IntelliJ IDEA or Eclipse. The project should have a main application class, typically found in src/main/java/com/yourcompany/yourapplication.

Run the Spring Boot Application

Execute the main application class to start your Spring Boot application. By default, it will run on localhost:8080.

Example of Spring boot application class 

package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}


This code snippet sets up a simple Spring Boot application that can be accessed through a web browser. The @SpringBootApplication annotation marks the class as a configuration class that declares one or more @Bean methods and triggers auto-configuration and component scanning.

Spring Boot Error Handler

Spring Boot provides a default error handling mechanism that kicks in when an exception occurs within your application. This default error handler is responsible for catching exceptions & returning appropriate error responses to the client.

Spring Boot provides several mechanisms to manage exceptions gracefully. One common approach is using the @ControllerAdvice and @ExceptionHandler annotations to handle exceptions globally.

Centralized Exception Handling with @ControllerAdvice

@ControllerAdvice allows you to handle exceptions across the whole application, not just to an individual controller. It's particularly useful for handling exceptions that occur in multiple controllers.

Here's how you can set up a basic error handler using @ControllerAdvice:

package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleAllExceptions(Exception ex) {
        ApiError apiError = new ApiError(
            HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "An error occurred");
        return new ResponseEntity<>(apiError, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
class ApiError {
    private HttpStatus status;
    private String message;
    private String details;
    public ApiError(HttpStatus status, String message, String details) {
        this.status = status;
        this.message = message;
        this.details = details;
    }
    // Getters & Setters
}


This example introduces a GlobalExceptionHandler class annotated with @ControllerAdvice. It includes a method to handle all exceptions, returning a ResponseEntity with a custom ApiError object containing the error details, status, and a user-friendly message.

Key Points

  1. @ExceptionHandler: This annotation is used to define a method in your @ControllerAdvice class that will handle exceptions thrown by methods annotated with @RequestMapping and similar.
     
  2. ResponseEntity: Wraps the response object, providing control over HTTP status codes.
     

Note :  With the help of custom error handler, you have more control over how errors are handled & presented to the user.

Handling Exceptions

When it comes to handling exceptions in Spring Boot, there are several approaches you can take. One common approach is to use exception handlers, which allow you to define methods that will be invoked when specific exceptions occur.

Custom Exception Handling in Controllers

You can use the @ExceptionHandler annotation within a controller to handle exceptions that are specific to the actions performed by that controller. This method allows for more precise control over exception responses based on the context of the controller.

Here is how you can implement it:

package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<Object> handleUserNotFoundException(UserNotFoundException ex) {
        ApiError apiError = new ApiError(
            HttpStatus.NOT_FOUND, ex.getMessage(), "User not found");
        return new ResponseEntity<>(apiError, HttpStatus.NOT_FOUND);
    }
    // Other controller methods
}
class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}


In this example, the UserController class handles a specific type of exception called UserNotFoundException. When this exception is thrown within this controller, the handleUserNotFoundException method crafts a specific ResponseEntity response.

Key Concepts

  1. Specificity in Exception Handling: This approach is useful for addressing specific exceptions that may not be relevant across the entire application.
     
  2. Decoupling of Error Handling: Allows each controller to manage its error responses, helping maintain cleaner code and separation of concerns.

Alternatively, you can create a global exception handler class that handles exceptions across your entire application. This is useful when you want to centralize exception handling logic.

Example of a global exception handler class

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(UserNotFoundException.class)
    public String handleUserNotFoundException(UserNotFoundException ex, Model model) {
        model.addAttribute("errorMessage", ex.getMessage());
        return "error";
    }
    @ExceptionHandler(Exception.class)
    public String handleGenericException(Exception ex, Model model) {
        model.addAttribute("errorMessage", "An error occurred");
        return "error";
    }
}


In this example, the GlobalExceptionHandler class is annotated with @ControllerAdvice, indicating that it serves as a global exception handler. It defines exception handling methods for specific exceptions, such as UserNotFoundException, as well as a generic exception handler for any other exceptions.

Note: By using exception handlers, you can centralize the exception handling logic & provide appropriate error responses to the client.

Overriding Exceptions Handled in ResponseEntityExceptionHandler:

Spring Boot provides a convenient base class called ResponseEntityExceptionHandler that offers a set of built-in exception handling methods. These methods handle common exceptions & return appropriate error responses. However, you may want to override these methods to customize the error handling behavior.

To override the exception handling methods in ResponseEntityExceptionHandler, you need to create a custom exception handler class that extends ResponseEntityExceptionHandler.

Here's an example of a custom exception handler that overrides the handleHttpMessageNotReadable() method:

@ControllerAdvice

public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(
            HttpMessageNotReadableException ex,
            HttpHeaders headers,
            HttpStatus status,
            WebRequest request) {
        
        String errorMessage = "Malformed JSON request";
        return buildResponseEntity(new ApiError(HttpStatus.BAD_REQUEST, errorMessage, ex));
    }
    private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
        return new ResponseEntity<>(apiError, apiError.getStatus());
    }
    // Other exception handling methods...
}
class ApiError {
    private HttpStatus status;
    private String message;
    private String debugMessage;

    // Constructor, getters, and setters...
}


In this example, the CustomExceptionHandler class extends ResponseEntityExceptionHandler. It overrides the handleHttpMessageNotReadable() method, which is invoked when the request body cannot be parsed (e.g., due to malformed JSON).

Inside the overridden method, you can customize the error response by creating an instance of ApiError, which contains the error details such as the HTTP status, error message, & debug message. The buildResponseEntity() method is a helper method that creates a ResponseEntity with the ApiError object & the appropriate HTTP status.

Note: By extending ResponseEntityExceptionHandler, you can selectively override the exception handling methods that you want to customize while keeping the default behavior for the rest.

Implementing Custom Exceptions:

In addition to handling built-in exceptions, you can also create custom exceptions to represent specific error scenarios in your application. Custom exceptions allow you to provide more meaningful & specific error messages to the client.

To create a custom exception, you need to define a new class that extends either the Exception class or one of its subclasses, such as RuntimeException.

Here's an example of a custom exception class:

public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}


In this example, the UserNotFoundException class extends RuntimeException & provides a constructor that accepts an error message. You can throw this custom exception in your code when a user is not found.

To handle custom exceptions, you can use the @ExceptionHandler annotation in your controller or global exception handler class.

Here's an example of handling a custom exception in a controller:

@Controller
public class UserController {
   @GetMapping("/users/{id}")
    public String getUserById(@PathVariable("id") Long id) {
        // Retrieve user logic
        // ...
        if (user == null) {
            throw new UserNotFoundException("User not found with ID: " + id);
        }
        return "user";
    }
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<Object> handleUserNotFoundException(UserNotFoundException ex) {
        String errorMessage = ex.getMessage();
        return buildResponseEntity(new ApiError(HttpStatus.NOT_FOUND, errorMessage, ex));
    }
    private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
        return new ResponseEntity<>(apiError, apiError.getStatus());
    }
}


In this example, the getUserById() method throws a UserNotFoundException if the user is not found. The @ExceptionHandler annotation is used to define a method that handles the UserNotFoundException. Inside the exception handling method, you can create an ApiError object with the appropriate HTTP status, error message, & the exception itself. The buildResponseEntity() method is used to create a ResponseEntity with the ApiError object.

Note: By implementing custom exceptions, you can provide more specific & meaningful error messages to the client, making it easier to understand & handle errors in your application.

Advantages of Custom Exceptions

  1. Clarity and Specificity: They allow you to create specific error codes and messages that can directly relate to the particular conditions of failure.
     
  2. Ease of Use: Integrating custom exceptions into your global exception handling strategy simplifies your error handling code, making it easier to maintain.
     
  3. Improved Client Communication: Custom exceptions ensure that the client receives a clear and concise explanation of what went wrong, enhancing the API's usability.

The Importance of Spring Boot Exception Handling:

  1. Improved User Experience: By handling exceptions effectively, you can provide informative error messages to users, guiding them on how to resolve issues or take appropriate actions. This enhances the overall user experience & reduces frustration.
     
  2. Maintainability: Centralized exception handling makes your codebase more maintainable. Instead of scattered error handling logic throughout your application, you can define exception handlers in a single place, making it easier to manage & update error handling behavior.
     
  3. Debugging & Troubleshooting: Exception handling helps in identifying & diagnosing issues during development & production. By logging exceptions & their stacktraces, you can quickly pinpoint the source of errors & take necessary corrective measures.
     
  4. Security: Proper exception handling is crucial for security reasons. You should avoid exposing sensitive information, such as system details or stack traces, to end-users. Exception handling allows you to control what information is sent back to the client in error responses.
     
  5. Reliability: By handling exceptions gracefully, you prevent your application from crashing or becoming unresponsive. Exception handling ensures that your application can recover from errors & continue functioning, providing a reliable experience to users.
     

To effectively handle exceptions in Spring Boot, consider the following best practices:

  • Use exception handlers to centralize error handling logic.
     
  • Provide meaningful & user-friendly error messages.
     
  • Log exceptions & their stacktraces for debugging purposes.
     
  • Use appropriate HTTP status codes to indicate the type of error.
     
  • Avoid exposing sensitive information in error responses.
     
  • Customize exception handling behavior based on your application's specific requirements.

Frequently Asked Questions

What is the difference between @ControllerAdvice & @ExceptionHandler?

@ControllerAdvice allows global handling of exceptions across multiple controllers, while @ExceptionHandler is used within a specific controller to handle exceptions locally to that controller.

Can I create custom exceptions for any type of error?

Yes, you can create custom exceptions for any specific error condition in your application, allowing for more targeted error messages and responses.

How does overriding methods in ResponseEntityExceptionHandler improve error handling?

Overriding these methods enables you to customize the HTTP responses for certain exceptions, providing more detailed error information and improving the user experience.

Conclusion

In this article, we have discussed exception handling in Spring Boot. We started by setting up a Spring Boot project & learned about the default error handling mechanism. We then looked into various approaches to handle exceptions, including using exception handlers & overriding exceptions in the ResponseEntityExceptionHandler. We also covered the implementation of custom exceptions to provide specific error messages. Finally, we discussed the importance of exception handling in building robust & reliable Spring Boot applications.

You can refer to our guided paths on Code 360. You can check our course to learn more about DSADBMSCompetitive ProgrammingPythonJavaJavaScript, etc. Also, check out some of the Guided Paths on topics such as Data Structure andAlgorithmsCompetitive ProgrammingOperating SystemsComputer Networks, DBMSSystem Design, etc., as well as some Contests, Test Series, and Interview Experiences curated by top Industry.

Live masterclass