Error Handling
In previous lessons, we implemented category management endpoints that could potentially encounter various error conditions.
Now we'll create a centralized error handling system to provide consistent, user-friendly error responses across our API.
This error handling system will ensure our frontend can display meaningful messages to users when things go wrong.
Implementing the Error Controller
Spring's @ControllerAdvice annotation enables global exception handling across all our controllers.
Let's create the ErrorController class in our controllers package:
package com.devtiro.blog.controllers;
import com.devtiro.blog.domain.dtos.ApiErrorResponse;
import lombok.extern.slf4j.Slf4j;
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 org.springframework.web.bind.annotation.RestController;
@RestController
@ControllerAdvice
@Slf4j
public class ErrorController {
@ExceptionHandler(Exception.class)
public ResponseEntity<ApiErrorResponse> handleException(Exception ex) {
log.error("Caught exception", ex);
ApiErrorResponse error = ApiErrorResponse.builder()
.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
.message("An unexpected error occurred")
.build();
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
}Creating the Error Response DTO
Our API needs a standardized error response format to ensure consistent error handling across all endpoints.
Let's create the ApiErrorResponse class:
package com.devtiro.blog.domain.dtos;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApiErrorResponse {
private int status;
private String message;
private List<FieldError> errors;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class FieldError {
private String field;
private String message;
}
}Handling Specific Exceptions
Our category creation endpoint throws IllegalArgumentException when a duplicate category is detected.
Let's add specific handling for this case:
@RestController
@ControllerAdvice
@Slf4j
public class ErrorController {
// ... existing methods ...
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ApiErrorResponse> handleIllegalArgumentException(
IllegalArgumentException ex) {
ApiErrorResponse error = ApiErrorResponse.builder()
.status(HttpStatus.BAD_REQUEST.value())
.message(ex.getMessage())
.build();
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
}Summary
- Created centralized error handling using
@ControllerAdvice - Implemented standardized error response format with
ApiErrorResponse - Added specific handling for
IllegalArgumentException - Enabled detailed error logging for debugging
- Ensured consistent HTTP status codes for different error types