Exception handling in Spring Boot

In Spring Boot, exception handling is usually done with the @ControllerAdvice and @ExceptionHandler annotations. This helps you catch exceptions globally and return proper responses (e.g., JSON error messages) instead of exposing stack traces.

Here’s a simple example:


1. Create a Custom Exception

package com.example.demo.exception;

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

2. Service/Controller that throws Exception

package com.example.demo.controller;

import com.example.demo.exception.ResourceNotFoundException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @GetMapping("/users/{id}")
    public String getUser(@PathVariable int id) {
        if (id != 1) {
            throw new ResourceNotFoundException("User not found with id " + id);
        }
        return "User found with id " + id;
    }
}

3. Global Exception Handler

package com.example.demo.exception;

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 java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    // Handle specific exception
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<Object> handleResourceNotFound(ResourceNotFoundException ex) {
        Map<String, Object> body = new HashMap<>();
        body.put("timestamp", LocalDateTime.now());
        body.put("status", HttpStatus.NOT_FOUND.value());
        body.put("error", "Not Found");
        body.put("message", ex.getMessage());

        return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
    }

    // Handle generic exception
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleGeneralException(Exception ex) {
        Map<String, Object> body = new HashMap<>();
        body.put("timestamp", LocalDateTime.now());
        body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value());
        body.put("error", "Internal Server Error");
        body.put("message", ex.getMessage());

        return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

4. Example API Call

  • Request: GET http://localhost:8080/users/2
  • Response: { "timestamp": "2025-08-21T10:15:30", "status": 404, "error": "Not Found", "message": "User not found with id 2" }

✅ With this setup:

  • Specific exceptions (like ResourceNotFoundException) return meaningful JSON error messages.
  • Any other unhandled exceptions are caught by the generic ExceptionHandler.

Leave a Reply