From 0bdc3d6e1e9890c542f8d8797570cdf05d595538 Mon Sep 17 00:00:00 2001 From: Vyacheslav Date: Thu, 19 Oct 2023 22:18:21 +0300 Subject: [PATCH 1/3] Validation added --- pom.xml | 4 ++ .../bookstore/controller/BookController.java | 5 +- .../bookstore/dto/CreateBookRequestDto.java | 7 +++ .../exceptions/GlobalExceptionHandler.java | 46 +++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/bookstore/exceptions/GlobalExceptionHandler.java diff --git a/pom.xml b/pom.xml index 518022e..dacbfce 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,10 @@ liquibase-core ${liquibase.version} + + org.hibernate.validator + hibernate-validator + diff --git a/src/main/java/org/bookstore/controller/BookController.java b/src/main/java/org/bookstore/controller/BookController.java index 5d76e9c..d6ded4a 100644 --- a/src/main/java/org/bookstore/controller/BookController.java +++ b/src/main/java/org/bookstore/controller/BookController.java @@ -1,5 +1,6 @@ package org.bookstore.controller; +import jakarta.validation.Valid; import java.util.List; import lombok.RequiredArgsConstructor; import org.bookstore.dto.BookDto; @@ -31,13 +32,13 @@ public BookDto getBookById(@PathVariable Long id) { } @PostMapping - public BookDto createBook(@RequestBody CreateBookRequestDto bookRequestDto) { + public BookDto createBook(@RequestBody @Valid CreateBookRequestDto bookRequestDto) { return bookService.save(bookRequestDto); } @PutMapping("/{id}") public void updateBookById(@PathVariable Long id, - @RequestBody CreateBookRequestDto bookRequestDto) { + @RequestBody @Valid CreateBookRequestDto bookRequestDto) { bookService.updateBookById(id, bookRequestDto); } diff --git a/src/main/java/org/bookstore/dto/CreateBookRequestDto.java b/src/main/java/org/bookstore/dto/CreateBookRequestDto.java index 70977a2..c7006ef 100644 --- a/src/main/java/org/bookstore/dto/CreateBookRequestDto.java +++ b/src/main/java/org/bookstore/dto/CreateBookRequestDto.java @@ -1,14 +1,21 @@ package org.bookstore.dto; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; import lombok.Data; @Data public class CreateBookRequestDto { private Long id; + @NotNull private String title; + @NotNull private String author; + @NotNull private String isbn; + @NotNull + @Min(0) private BigDecimal price; private String description; private String coverImage; diff --git a/src/main/java/org/bookstore/exceptions/GlobalExceptionHandler.java b/src/main/java/org/bookstore/exceptions/GlobalExceptionHandler.java new file mode 100644 index 0000000..803d5db --- /dev/null +++ b/src/main/java/org/bookstore/exceptions/GlobalExceptionHandler.java @@ -0,0 +1,46 @@ +package org.bookstore.exceptions; + +import java.time.LocalDateTime; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +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.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + @Override + protected ResponseEntity handleMethodArgumentNotValid( + MethodArgumentNotValidException ex, + HttpHeaders headers, + HttpStatusCode status, + WebRequest request) { + Map body = new LinkedHashMap<>(); + body.put("time", LocalDateTime.now()); + body.put("status", HttpStatus.BAD_REQUEST); + List error = ex.getBindingResult().getAllErrors() + .stream() + .map(this::getErrorMessage) + .collect(Collectors.toList()); + body.put("errors", error); + return new ResponseEntity<>(body, headers, status); + } + + private String getErrorMessage(ObjectError objectError) { + if (objectError instanceof FieldError) { + String field = ((FieldError) objectError).getField(); + String message = objectError.getDefaultMessage(); + return field + " " + message; + } + return objectError.getDefaultMessage(); + } +} From 21f4de49440456caf69bd4d793015e55aa3b3512 Mon Sep 17 00:00:00 2001 From: Vyacheslav Date: Fri, 20 Oct 2023 19:44:11 +0300 Subject: [PATCH 2/3] Renamed update methode, @Repository annotation added --- pom.xml | 13 ++++--------- src/main/java/org/bookstore/mapper/BookMapper.java | 2 +- .../org/bookstore/repository/BookRepository.java | 2 ++ .../org/bookstore/service/impl/BookServiceImpl.java | 2 +- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index dacbfce..1c8f67d 100644 --- a/pom.xml +++ b/pom.xml @@ -20,6 +20,10 @@ 0.2.0 + + org.hibernate.validator + hibernate-validator + org.springframework.boot spring-boot-starter @@ -56,15 +60,6 @@ org.projectlombok lombok - - org.liquibase - liquibase-core - ${liquibase.version} - - - org.hibernate.validator - hibernate-validator - diff --git a/src/main/java/org/bookstore/mapper/BookMapper.java b/src/main/java/org/bookstore/mapper/BookMapper.java index 5b89309..1dfa9e1 100644 --- a/src/main/java/org/bookstore/mapper/BookMapper.java +++ b/src/main/java/org/bookstore/mapper/BookMapper.java @@ -18,5 +18,5 @@ public interface BookMapper { Book toBook(CreateBookRequestDto bookRequestDto); - void updateBookFromDto(CreateBookRequestDto book, @MappingTarget Book entity); + void updateBook(CreateBookRequestDto book, @MappingTarget Book entity); } diff --git a/src/main/java/org/bookstore/repository/BookRepository.java b/src/main/java/org/bookstore/repository/BookRepository.java index bece062..7781513 100644 --- a/src/main/java/org/bookstore/repository/BookRepository.java +++ b/src/main/java/org/bookstore/repository/BookRepository.java @@ -2,7 +2,9 @@ import org.bookstore.model.Book; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface BookRepository extends JpaRepository { } diff --git a/src/main/java/org/bookstore/service/impl/BookServiceImpl.java b/src/main/java/org/bookstore/service/impl/BookServiceImpl.java index 5c77c64..353e383 100644 --- a/src/main/java/org/bookstore/service/impl/BookServiceImpl.java +++ b/src/main/java/org/bookstore/service/impl/BookServiceImpl.java @@ -42,7 +42,7 @@ public BookDto findById(Long id) { public BookDto updateBookById(Long id, CreateBookRequestDto book) { Book bookFromDb = bookRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Can't update book with id " + id)); - bookMapper.updateBookFromDto(book, bookFromDb); + bookMapper.updateBook(book, bookFromDb); return bookMapper.toDto(bookRepository.save(bookFromDb)); } From 29e2ce89ee69dce1dcb84c93d86311b5d0ce49f8 Mon Sep 17 00:00:00 2001 From: Vyacheslav Date: Fri, 20 Oct 2023 19:51:30 +0300 Subject: [PATCH 3/3] Annotations changed from NotNull to NotBlank, Min(0) to PositiveOrZero --- .../org/bookstore/dto/CreateBookRequestDto.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/bookstore/dto/CreateBookRequestDto.java b/src/main/java/org/bookstore/dto/CreateBookRequestDto.java index c7006ef..79997a1 100644 --- a/src/main/java/org/bookstore/dto/CreateBookRequestDto.java +++ b/src/main/java/org/bookstore/dto/CreateBookRequestDto.java @@ -1,21 +1,20 @@ package org.bookstore.dto; -import jakarta.validation.constraints.Min; -import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.PositiveOrZero; import java.math.BigDecimal; import lombok.Data; @Data public class CreateBookRequestDto { private Long id; - @NotNull + @NotBlank private String title; - @NotNull + @NotBlank private String author; - @NotNull + @NotBlank private String isbn; - @NotNull - @Min(0) + @PositiveOrZero private BigDecimal price; private String description; private String coverImage;