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
© 2026 Devtiro Ltd. All rights reserved