0
0
SpringbootHow-ToBeginner · 4 min read

How to Use @ControllerAdvice in Spring for Global Exception Handling

Use @ControllerAdvice to create a class that handles exceptions globally across all controllers in a Spring application. Annotate methods inside this class with @ExceptionHandler to define how specific exceptions should be processed and what response to send.
📐

Syntax

The @ControllerAdvice annotation marks a class as a global handler for exceptions and other controller-related concerns. Inside this class, methods annotated with @ExceptionHandler specify which exceptions they handle. You can also use @ResponseStatus to set HTTP status codes for responses.

  • @ControllerAdvice: Declares a global handler class.
  • @ExceptionHandler(ExceptionType.class): Handles specific exceptions.
  • @ResponseStatus(HttpStatus.CODE): Sets HTTP status for the response.
java
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handleIllegalArgument(IllegalArgumentException ex) {
        return ex.getMessage();
    }
}
💻

Example

This example shows a Spring Boot application with a controller that throws an exception and a @ControllerAdvice class that catches it globally. The handler returns a custom error message with HTTP 400 status.

java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
class SampleController {
    @GetMapping("/test")
    public String test(@RequestParam(required = false) String input) {
        if (input == null) {
            throw new IllegalArgumentException("Input parameter is missing");
        }
        return "Input was: " + input;
    }
}

@ControllerAdvice
class GlobalExceptionHandler {
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handleIllegalArgument(IllegalArgumentException ex) {
        return "Error: " + ex.getMessage();
    }
}
Output
GET /test?input=hello --> 200 OK, body: "Input was: hello" GET /test --> 400 BAD REQUEST, body: "Error: Input parameter is missing"
⚠️

Common Pitfalls

  • Not annotating the handler class with @ControllerAdvice means exceptions won't be caught globally.
  • Forgetting @ExceptionHandler on methods causes them not to handle exceptions.
  • Returning raw strings without proper response formatting can cause unclear client responses.
  • Using @ResponseStatus incorrectly may send wrong HTTP status codes.
java
/* Wrong: Missing @ControllerAdvice */
public class WrongHandler {
    @ExceptionHandler(NullPointerException.class)
    public String handleNullPointer(NullPointerException ex) {
        return "Null error";
    }
}

/* Right: With @ControllerAdvice */
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class RightHandler {
    @ExceptionHandler(NullPointerException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String handleNullPointer(NullPointerException ex) {
        return "Null error occurred";
    }
}
📊

Quick Reference

@ControllerAdvice creates a global exception handler class.

@ExceptionHandler(Exception.class) marks methods to handle specific exceptions.

@ResponseStatus(HttpStatus.CODE) sets the HTTP status code for the response.

Use these together to centralize error handling and keep controllers clean.

AnnotationPurpose
@ControllerAdviceMarks a class as a global exception handler
@ExceptionHandler(ExceptionType.class)Handles specific exceptions in methods
@ResponseStatus(HttpStatus.CODE)Sets HTTP status code for the response
@RestControllerAdviceShortcut for @ControllerAdvice + @ResponseBody

Key Takeaways

Use @ControllerAdvice to handle exceptions globally across all controllers.
Annotate methods with @ExceptionHandler to specify which exceptions to catch.
Set HTTP status codes with @ResponseStatus for clear client responses.
Without @ControllerAdvice, exception handlers won't apply globally.
Keep controllers clean by moving error handling to a dedicated advice class.