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 create clean, consistent REST API error responses with real Java examples.


Introduction

Imagine you’re using a banking app. You enter the wrong account number, and instead of a friendly error message, the app crashes or shows a confusing technical stack trace. As a user, that’s frustrating. As a developer, it’s embarrassing.

This is exactly why global exception handling in Spring Boot is so important.

When beginners start building REST APIs in Java programming, they often handle errors directly inside controllers—using try-catch blocks everywhere. This quickly turns code messy, repetitive, and hard to maintain.

Spring Boot provides a clean and powerful way to handle exceptions centrally, ensuring:

  • Consistent error responses
  • Cleaner controllers
  • Better debugging and logging
  • A more professional API experience

In this blog, you’ll learn what global exception handling is, why it matters, and how to implement it step by step using simple, beginner-friendly Java 21 examples.


Core Concepts

What Is Exception Handling?

An exception is an unexpected situation that occurs during program execution—like:

  • Resource not found
  • Invalid input
  • Database failure
  • Unauthorized access

If not handled properly, exceptions can:

  • Crash your application
  • Expose sensitive details
  • Confuse API consumers

What Is Global Exception Handling in Spring Boot?

Global exception handling means handling all exceptions in one centralized place, instead of scattering try-catch blocks across controllers.

👉 Analogy: Customer Support Desk

Instead of every shop handling complaints differently, all complaints go to a single help desk that responds in a standard way. That’s exactly what global exception handling does for your API.

Spring Boot achieves this using:

  • @ExceptionHandler
  • @ControllerAdvice / @RestControllerAdvice

Why Use Global Exception Handling?

Key benefits:

  • Cleaner controller code
  • Consistent API error responses
  • Easy maintenance and scalability
  • Better separation of concerns
  • Improved API security (no stack trace leaks)

This approach is considered a best practice in modern Spring Boot applications.


Code Examples (Java 21)

Example 1: Handling a Custom Exception Globally

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 in 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 here—clean and readable.


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:

  • Any ResourceNotFoundException is handled centrally
  • Controller code stays clean
  • API returns a proper HTTP status

Example 2: Handling Multiple Exceptions with a Common Response

Create an Error Response DTO

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

Global Handler for Multiple Exceptions

@RestControllerAdvice
public class GlobalExceptionHandler {

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

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

        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}
Enter fullscreen mode Exit fullscreen mode

📌 This produces structured, consistent error responses—ideal for REST APIs.


Best Practices (3–5 Tips)

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

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

  3. Never expose stack traces to clients
    Log internally, respond cleanly.

  4. Standardize error responses
    Use a common error DTO for all APIs.

  5. Map correct HTTP status codes
    400 for bad requests, 404 for not found, 500 for server errors.


Common Mistakes to Avoid

❌ Using try-catch in every controller
❌ Returning 200 OK for error scenarios
❌ Exposing internal exception messages
❌ Mixing business logic with error handling


Conclusion

Global exception handling in Spring Boot is a must-have skill for anyone serious about building production-ready Java applications. By centralizing error handling with @RestControllerAdvice, you keep your controllers clean, your APIs consistent, and your users happy.

Instead of reacting to errors everywhere, you design a single, reliable strategy for handling them. This approach scales beautifully as your application grows and is widely expected in real-world Spring Boot projects and interviews.

If you’re learning Spring Boot, mastering global exception handling is a big step toward writing professional-quality Java code.


Top comments (0)