Error Handling

When building REST APIs, proper error handling ensures users receive clear, consistent responses when things go wrong.

Creating the Error DTO

To standardize our error responses, we'll create an ErrorDto class that defines the structure of error messages sent to API clients.

The ErrorDto class uses Lombok annotations to reduce boilerplate code and includes two fields: status for the HTTP status code and message for the error description.

@Data @AllArgsConstructor @NoArgsConstructor @Builder public class ErrorDto { private Integer status; private String message; }

Implementing Global Error Handling

Spring's @ControllerAdvice annotation allows us to handle exceptions across our entire application in one place.

We'll create an ErrorController class that catches and processes different types of exceptions:

@RestController @ControllerAdvice @Slf4j public class ErrorController { // Handle storage-related exceptions @ExceptionHandler(StorageException.class) public ResponseEntity<ErrorDto> handleStorageException(StorageException ex) { log.error("Caught StorageException exception", ex); ErrorDto error = ErrorDto.builder() .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) .message("Unable to save or recall the resource at this time") .build(); return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR); } // Handle our base application exception @ExceptionHandler(BaseException.class) public ResponseEntity<ErrorDto> handleBaseException(BaseException ex) { log.error("Caught BaseException", ex); ErrorDto error = ErrorDto.builder() .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) .message("An unexpected error occurred") .build(); return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR); } // Catch-all for unexpected exceptions @ExceptionHandler(Exception.class) public ResponseEntity<ErrorDto> handleException(Exception ex) { log.error("Caught unexpected exception", ex); ErrorDto error = ErrorDto.builder() .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) .message("An unexpected error occurred") .build(); return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR); } }

This implementation builds on our custom exceptions from previous lessons, particularly the StorageException we created for file operations.

Each handler method logs the error and returns an appropriate error response.

Summary

  • Created ErrorDto to standardize API error responses
  • Implemented global error handling with @ControllerAdvice
  • Added specific handlers for StorageException and BaseException
  • Included logging for debugging and monitoring
  • Used ResponseEntity to control HTTP status codes
© 2026 Devtiro Ltd. All rights reserved