From 99a874db980aa319834b8fb170baaab7c2addcbe Mon Sep 17 00:00:00 2001 From: Oksana Miazina Date: Thu, 2 May 2024 16:23:19 +0300 Subject: [PATCH] feat: change response error format --- .../BookControllerExceptionHandler.java | 65 +++++++++++-------- .../bookstore/handler/ErrorMessage.java | 4 ++ .../bookstore/handler/ResponseData.java | 22 +++++++ 3 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 src/main/java/mate/academy/bookstore/handler/ErrorMessage.java create mode 100644 src/main/java/mate/academy/bookstore/handler/ResponseData.java diff --git a/src/main/java/mate/academy/bookstore/handler/BookControllerExceptionHandler.java b/src/main/java/mate/academy/bookstore/handler/BookControllerExceptionHandler.java index f41f929..f0cee47 100644 --- a/src/main/java/mate/academy/bookstore/handler/BookControllerExceptionHandler.java +++ b/src/main/java/mate/academy/bookstore/handler/BookControllerExceptionHandler.java @@ -1,60 +1,69 @@ package mate.academy.bookstore.handler; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.List; import mate.academy.bookstore.exception.EntityNotFoundException; import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.data.mapping.PropertyReferenceException; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; @ControllerAdvice public class BookControllerExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) @ResponseBody - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException ex) { - return getResponseEntity(HttpStatus.NOT_FOUND, ex.getMessage()); + @ResponseStatus(HttpStatus.NOT_FOUND) + public ResponseData handleEntityNotFoundException(EntityNotFoundException ex) { + return new ResponseData( + HttpStatus.NOT_FOUND, + null, + List.of(new ErrorMessage("", ex.getMessage())) + ); } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody - public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex) { - Map errors = new HashMap<>(); - ex.getBindingResult().getAllErrors().forEach(error -> { - Map.Entry errorMessage = getErrorMessage(error); - errors.put(errorMessage.getKey(), errorMessage.getValue()); - }); + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseData handleValidationExceptions(MethodArgumentNotValidException ex) { + List errors = ex.getBindingResult().getAllErrors().stream() + .map(this::getErrorMessage) + .toList(); + return new ResponseData(HttpStatus.BAD_REQUEST, null, errors); + } - return getResponseEntity(HttpStatus.BAD_REQUEST, errors); + @ExceptionHandler(PropertyReferenceException.class) + @ResponseBody + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ResponseData handlePropertyReferenceException(PropertyReferenceException ex) { + return new ResponseData( + HttpStatus.BAD_REQUEST, + null, + List.of(new ErrorMessage("", ex.getMessage())) + ); } @ExceptionHandler(DataIntegrityViolationException.class) @ResponseBody - public ResponseEntity handleDataIntegrityViolationException( + @ResponseStatus(HttpStatus.CONFLICT) + public ResponseData handleDataIntegrityViolationException( DataIntegrityViolationException ex) { - return getResponseEntity(HttpStatus.CONFLICT, ex.getMessage()); + return new ResponseData( + HttpStatus.CONFLICT, + null, + List.of(new ErrorMessage("", ex.getMessage())) + ); } - private Map.Entry getErrorMessage(ObjectError e) { + private ErrorMessage getErrorMessage(ObjectError e) { + String field = ""; if (e instanceof FieldError fieldError) { - String field = fieldError.getField(); - String message = e.getDefaultMessage(); - return Map.entry(field, message); + field = fieldError.getField(); } - return Map.entry("", e.getDefaultMessage()); - } - - private ResponseEntity getResponseEntity(HttpStatus status, Object errors) { - Map body = new LinkedHashMap<>(); - body.put("success", status.is2xxSuccessful()); - body.put("errors", errors); - return new ResponseEntity<>(body, status); + return new ErrorMessage(field, e.getDefaultMessage()); } } - diff --git a/src/main/java/mate/academy/bookstore/handler/ErrorMessage.java b/src/main/java/mate/academy/bookstore/handler/ErrorMessage.java new file mode 100644 index 0000000..c8114ca --- /dev/null +++ b/src/main/java/mate/academy/bookstore/handler/ErrorMessage.java @@ -0,0 +1,4 @@ +package mate.academy.bookstore.handler; + +public record ErrorMessage(String field, String message) { +} diff --git a/src/main/java/mate/academy/bookstore/handler/ResponseData.java b/src/main/java/mate/academy/bookstore/handler/ResponseData.java new file mode 100644 index 0000000..f238bf3 --- /dev/null +++ b/src/main/java/mate/academy/bookstore/handler/ResponseData.java @@ -0,0 +1,22 @@ +package mate.academy.bookstore.handler; + +import java.util.List; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +public class ResponseData { + private boolean success; + + private int status; + private Object data; + private List errors; + + public ResponseData(HttpStatus status, Object data, List errors) { + this.data = data; + this.errors = errors; + this.status = status.value(); + this.success = status.is2xxSuccessful(); + } +} +