In Spring MVC, handle exceptions globally by creating a class annotated with @ControllerAdvice or @RestControllerAdvice and adding methods annotated with @ExceptionHandler.
For REST APIs, prefer @RestControllerAdvice, because it combines @ControllerAdvice and @ResponseBody, so returned objects are serialized as JSON automatically.
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFoundException(
ResourceNotFoundException ex
) {
ErrorResponse error = new ErrorResponse(
HttpStatus.NOT_FOUND.value(),
ex.getMessage()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(
Exception ex
) {
ErrorResponse error = new ErrorResponse(
HttpStatus.INTERNAL_SERVER_ERROR.value(),
"An unexpected error occurred"
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
Example error response DTO:
package com.example.demo.exception;
import java.time.Instant;
public record ErrorResponse(
int status,
String message,
Instant timestamp
) {
public ErrorResponse(int status, String message) {
this(status, message, Instant.now());
}
}
Example custom exception:
package com.example.demo.exception;
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
Then you can throw exceptions from controllers or services:
throw new ResourceNotFoundException("User not found");
Spring will automatically route that exception to the matching @ExceptionHandler.
Common handlers you may want to add:
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(
MethodArgumentNotValidException ex
) {
ErrorResponse error = new ErrorResponse(
HttpStatus.BAD_REQUEST.value(),
"Validation failed"
);
return ResponseEntity.badRequest().body(error);
}
Use:
@RestControllerAdvicefor REST APIs returning JSON.@ControllerAdvicefor MVC apps returning views or when you manually useResponseEntity.- Specific exception handlers before generic ones.
- A final
@ExceptionHandler(Exception.class)as a fallback.
