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
ErrorDtoto standardize API error responses - Implemented global error handling with
@ControllerAdvice - Added specific handlers for
StorageExceptionandBaseException - Included logging for debugging and monitoring
- Used
ResponseEntityto control HTTP status codes