DEV Community

realNameHidden
realNameHidden

Posted on

How Do You Handle Exceptions Globally in Spring Boot?

Learn how to implement global exception handling in Spring Boot to build clean, consistent REST API error responses with practical Java examples.


Introduction

Imagine you’re calling a REST API from a frontend application. Instead of a clear error message like “User not found”, you suddenly receive a long stack trace or a generic 500 Internal Server Error. As a user, this is confusing. As a developer, it’s frustrating.

This is where global exception handling in Spring Boot becomes essential.

When developers start learning Java programming and Spring Boot, they often use try-catch blocks inside every controller. While this works initially, it quickly leads to messy code, duplicated logic, and inconsistent error responses.

Spring Boot offers a clean, centralized way to handle all exceptions in one place. This approach improves code readability, API consistency, and overall application quality. In this blog, you’ll learn how global exception handling works in Spring Boot, why it’s important, and how to implement it using beginner-friendly Java 21 examples.


Core Concepts

What Is Exception Handling?

An exception is an unexpected event that disrupts the normal flow of a program. Examples include:

  • Invalid input from a client
  • Requested resource not found
  • Database connection failures
  • Unauthorized access

If exceptions are not handled properly, they can crash the application or expose sensitive internal details.


What Is Global Exception Handling in Spring Boot?

Global exception handling means managing all application errors from a single, centralized component instead of handling them individually in every controller.

👉 Analogy: Central Help Desk

In a company, employees don’t solve every issue themselves—they report it to a central help desk that responds in a standard way. Global exception handling works the same way for your APIs.

Spring Boot supports this using:

  • @ExceptionHandler
  • @ControllerAdvice or @RestControllerAdvice

Why Use Global Exception Handling?

Benefits:

  • Cleaner and simpler controller code
  • Consistent error responses across APIs
  • Easier maintenance and scalability
  • Improved security (no stack traces exposed)
  • Better client experience

This is why global exception handling in Spring Boot is considered a best practice for REST APIs.


Code Examples (Java 21)

Example 1: Global Handling of a Custom Exception

Step 1: Create a Custom Exception

public class ResourceNotFoundException extends RuntimeException {

    public ResourceNotFoundException(String message) {
        super(message);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Throw the Exception from a Controller

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public String getUser(@PathVariable Long id) {
        if (id != 1) {
            throw new ResourceNotFoundException("User not found with id: " + id);
        }
        return "User found";
    }
}
Enter fullscreen mode Exit fullscreen mode

📌 No try-catch blocks cluttering the controller.


Step 3: Create a Global Exception Handler

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<String> handleResourceNotFound(ResourceNotFoundException ex) {
        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(ex.getMessage());
    }
}
Enter fullscreen mode Exit fullscreen mode

✅ Result:

  • Centralized handling
  • Clean controller code
  • Proper HTTP status codes

Example 2: Structured Error Response for Multiple Exceptions

Create a Common Error Response Model

import java.time.LocalDateTime;

public record ErrorResponse(
        int status,
        String message,
        LocalDateTime timestamp
) {}
Enter fullscreen mode Exit fullscreen mode

Handle Multiple Exceptions Globally

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler({
            IllegalArgumentException.class,
            MethodArgumentTypeMismatchException.class
    })
    public ResponseEntity<ErrorResponse> handleBadRequest(Exception ex) {

        ErrorResponse errorResponse = new ErrorResponse(
                HttpStatus.BAD_REQUEST.value(),
                ex.getMessage(),
                LocalDateTime.now()
        );

        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(errorResponse);
    }
}
Enter fullscreen mode Exit fullscreen mode

📌 This ensures all error responses follow the same structure—ideal for frontend and API consumers.


Best Practices

  1. Use @RestControllerAdvice for REST APIs
    It automatically returns JSON responses.

  2. Create custom exceptions for business errors
    Avoid throwing generic RuntimeException.

  3. Return meaningful HTTP status codes
    Use 400, 404, 401, and 500 appropriately.

  4. Do not expose stack traces to clients
    Log errors internally, return clean messages.

  5. Standardize error responses
    A common error format improves API usability.


Common Mistakes to Avoid

❌ Handling exceptions inside every controller
❌ Returning 200 OK for error cases
❌ Exposing internal exception details
❌ Mixing business logic with error handling


Conclusion

Global exception handling in Spring Boot is a fundamental skill for building professional, production-ready applications. By centralizing error handling using @RestControllerAdvice, you keep your controllers clean, your APIs consistent, and your users informed.

Instead of reacting to errors in multiple places, you define a single strategy that scales as your application grows. This approach is widely expected in real-world Spring Boot projects and technical interviews.

If you’re learning Spring Boot or improving your REST API design, mastering global exception handling is a big step toward writing high-quality Java applications.


Top comments (0)