From a178f09ef49aaf21a3b8cc52690f3140302089b3 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Tue, 23 Jul 2019 21:53:15 +0530 Subject: [PATCH 01/14] BAEL-3005 | Validating List objects in Spring --- spring-mvc-simple-2/pom.xml | 4 ++ .../SpringListValidationApplication.java | 17 +++++ .../constraint/CustomConstraint.java | 18 +++++ .../constraint/CustomConstraintValidator.java | 17 +++++ .../controller/MovieController.java | 54 +++++++++++++++ .../ConstraintViolationExceptionHandler.java | 30 +++++++++ .../listvalidation/model/Actor.java | 22 +++++++ .../listvalidation/model/Movie.java | 41 ++++++++++++ .../repository/MovieRepository.java | 57 ++++++++++++++++ .../MovieControllerIntegrationTest.java | 65 +++++++++++++++++++ 10 files changed, 325 insertions(+) create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java create mode 100644 spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java diff --git a/spring-mvc-simple-2/pom.xml b/spring-mvc-simple-2/pom.xml index 74302cff78..2fe93f1fae 100644 --- a/spring-mvc-simple-2/pom.xml +++ b/spring-mvc-simple-2/pom.xml @@ -18,6 +18,10 @@ org.springframework.boot spring-boot-starter-web + + org.projectlombok + lombok + diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java new file mode 100644 index 0000000000..f16d5f877f --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java @@ -0,0 +1,17 @@ +package com.baeldung.validation.listvalidation; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@ComponentScan(basePackages = "com.baeldung.validation.listvalidation") +@Configuration +@SpringBootApplication +public class SpringListValidationApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringListValidationApplication.class, args); + } + +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java new file mode 100644 index 0000000000..5d6e2213f1 --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java @@ -0,0 +1,18 @@ +package com.baeldung.validation.listvalidation.constraint; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.validation.Constraint; +import javax.validation.Payload; + +@Constraint(validatedBy = CustomConstraintValidator.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface CustomConstraint { + + String message() default "Invalid movie name."; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java new file mode 100644 index 0000000000..9f18a0c218 --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java @@ -0,0 +1,17 @@ +package com.baeldung.validation.listvalidation.constraint; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class CustomConstraintValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + if (value == null || value.isEmpty()) { + return false; + } else { + return true; + } + } + +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java new file mode 100644 index 0000000000..6265fd50d0 --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java @@ -0,0 +1,54 @@ +package com.baeldung.validation.listvalidation.controller; + +import java.util.List; + +import javax.validation.Valid; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import com.baeldung.validation.listvalidation.model.Movie; +import com.baeldung.validation.listvalidation.repository.MovieRepository; + +@Validated +@RestController +@RequestMapping("/movie") +public class MovieController { + + private final Logger LOGGER = LoggerFactory.getLogger(MovieController.class); + + @Autowired + private MovieRepository movieRepository; + + @RequestMapping(method = RequestMethod.POST) + public void add(@RequestBody @Valid Movie movie, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + StringBuilder builder = new StringBuilder(); + bindingResult.getAllErrors() + .forEach(error -> builder.append(" " + error.getDefaultMessage())); + LOGGER.error(builder.toString()); + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, bindingResult.toString()); + } + movieRepository.add(movie); + } + + @RequestMapping(value = "/batch", method = RequestMethod.POST) + public void addAll(@RequestBody List<@Valid Movie> movie) { + movieRepository.addAll(movie); + } + + @RequestMapping(method = RequestMethod.GET, value = "/{name}") + public Movie get(@PathVariable String name) throws Exception { + return movieRepository.get(name); + } +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java new file mode 100644 index 0000000000..067a0e08ac --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java @@ -0,0 +1,30 @@ +package com.baeldung.validation.listvalidation.exception; + +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.ConstraintViolationException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ConstraintViolationExceptionHandler { + private final Logger LOGGER = LoggerFactory.getLogger(ConstraintViolationExceptionHandler.class); + + @ExceptionHandler(ConstraintViolationException.class) + public ResponseEntity handle(ConstraintViolationException constraintViolationException) { + Set> violations = constraintViolationException.getConstraintViolations(); + StringBuilder builder = new StringBuilder(); + for (ConstraintViolation violation : violations) { + builder.append(violation.getMessage()); + + } + LOGGER.error(builder.toString()); + return new ResponseEntity(builder.toString(), HttpStatus.BAD_REQUEST); + } +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java new file mode 100644 index 0000000000..e6215f00c4 --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java @@ -0,0 +1,22 @@ +package com.baeldung.validation.listvalidation.model; + +import java.util.UUID; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class Actor { + + private String id; + private String name; + + public Actor(String name) { + this.id = UUID.randomUUID() + .toString(); + this.name = name; + } +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java new file mode 100644 index 0000000000..7ab4bfc34e --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java @@ -0,0 +1,41 @@ +package com.baeldung.validation.listvalidation.model; + +import java.util.List; +import java.util.UUID; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.baeldung.validation.listvalidation.constraint.CustomConstraint; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class Movie { + + private String id; + + @CustomConstraint + private String name; + + @Size(min = 2, message = "Atleast 2 genres should be provided.") + private List genres; + + @NotNull(message = "Actor list cannot be null.") + @NotEmpty(message = "Actor list cannot be empty.") + private List actors; + + public Movie(String name, List genres, List actors) { + this.id = UUID.randomUUID() + .toString(); + this.name = name; + this.genres = genres; + this.actors = actors; + } + +} diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java new file mode 100644 index 0000000000..67cfa6daca --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java @@ -0,0 +1,57 @@ +package com.baeldung.validation.listvalidation.repository; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Repository; + +import com.baeldung.validation.listvalidation.model.Actor; +import com.baeldung.validation.listvalidation.model.Movie; + +@Repository +public class MovieRepository { + private final Logger LOGGER = LoggerFactory.getLogger(MovieRepository.class); + static List moviesData; + + static { + moviesData = new ArrayList<>(); + + Actor a1 = new Actor("Actor1"); + + Movie m1 = new Movie("MovieABC", Arrays.asList("Drama"), Arrays.asList(a1)); + moviesData.add(m1); + + Movie m2 = new Movie("MovieDEF", Arrays.asList("Drama"), Arrays.asList(a1)); + moviesData.add(m2); + + } + + public void add(Movie movie) { + if (get(movie.getName()) == null) { + moviesData.add(movie); + LOGGER.info("Added new movie."); + } + } + + public Movie get(String name) { + Movie movie = null; + for (Movie m : moviesData) { + if (name.equalsIgnoreCase(m.getName())) { + movie = m; + LOGGER.info("Found movie with name " + name + ":" + movie); + } + } + + return movie; + } + + public void addAll(List movies) { + for (Movie movie : movies) { + add(movie); + } + } + +} diff --git a/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java b/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java new file mode 100644 index 0000000000..226e609d5f --- /dev/null +++ b/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.validation.listvalidation; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import com.baeldung.validation.listvalidation.model.Actor; +import com.baeldung.validation.listvalidation.model.Movie; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SpringListValidationApplication.class) +@AutoConfigureMockMvc +public class MovieControllerIntegrationTest { + + @Autowired + private MockMvc mvc; + + ObjectMapper objectMapper = new ObjectMapper(); + + @Test + public void given1Genre_whenAddingMovie_thenThrowBadRequest() throws Exception { + Actor actor = new Actor("Actor1"); + Movie movie = new Movie("Movie1", Arrays.asList("Drama"), Arrays.asList(actor)); + mvc.perform(MockMvcRequestBuilders.post("/movie") + .contentType(MediaType.APPLICATION_JSON_UTF8) + .content(objectMapper.writeValueAsString(movie))) + .andExpect(MockMvcResultMatchers.status() + .isBadRequest()); + } + + @Test + public void givenWithoutActor_whenAddingMovieList_thenThrowBadRequest() throws Exception { + List actors = new ArrayList<>(); + Movie movie = new Movie("Movie2", Arrays.asList("Action", "Thriller"), actors); + mvc.perform(MockMvcRequestBuilders.post("/movie/batch") + .contentType(MediaType.APPLICATION_JSON_UTF8) + .content(objectMapper.writeValueAsString(Arrays.asList(movie)))) + .andExpect(MockMvcResultMatchers.status() + .isBadRequest()); + } + + @Test + public void givenEmptyMovieName_whenAddingMovie_thenThrowBadRequest() throws Exception { + Actor actor = new Actor("Actor1"); + Movie movie = new Movie("", Arrays.asList("Drama", "History"), Arrays.asList(actor)); + mvc.perform(MockMvcRequestBuilders.post("/movie") + .contentType(MediaType.APPLICATION_JSON_UTF8) + .content(objectMapper.writeValueAsString(movie))) + .andExpect(MockMvcResultMatchers.status() + .isBadRequest()); + } + +} From 98b5a7fdb72f1a0722b0d2a5196766add53f700d Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:24:59 +0530 Subject: [PATCH 02/14] BAEL-3005 | updated exception handler --- .../ConstraintViolationExceptionHandler.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java index 067a0e08ac..742be27f61 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java @@ -14,17 +14,23 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class ConstraintViolationExceptionHandler { - private final Logger LOGGER = LoggerFactory.getLogger(ConstraintViolationExceptionHandler.class); + + private final Logger logger = LoggerFactory.getLogger(ConstraintViolationExceptionHandler.class); @ExceptionHandler(ConstraintViolationException.class) public ResponseEntity handle(ConstraintViolationException constraintViolationException) { Set> violations = constraintViolationException.getConstraintViolations(); - StringBuilder builder = new StringBuilder(); - for (ConstraintViolation violation : violations) { - builder.append(violation.getMessage()); - + String errorMessage = ""; + if (!violations.isEmpty()) { + StringBuilder builder = new StringBuilder(); + violations.forEach(violation -> builder.append("\n" + violation.getMessage())); + errorMessage = builder.toString(); + } else { + errorMessage = "ConstraintViolationException occured."; } - LOGGER.error(builder.toString()); - return new ResponseEntity(builder.toString(), HttpStatus.BAD_REQUEST); + + logger.error(errorMessage); + return new ResponseEntity<>(errorMessage, HttpStatus.BAD_REQUEST); } + } From 6123255cf4f118feb83bb3d7bfb492cc206ac65c Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:28:56 +0530 Subject: [PATCH 03/14] BAEL--3005 | updated Movie POJO --- .../listvalidation/model/Movie.java | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java index 7ab4bfc34e..035c5f4412 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java @@ -1,13 +1,8 @@ package com.baeldung.validation.listvalidation.model; -import java.util.List; import java.util.UUID; import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - -import com.baeldung.validation.listvalidation.constraint.CustomConstraint; import lombok.Getter; import lombok.NoArgsConstructor; @@ -20,22 +15,13 @@ public class Movie { private String id; - @CustomConstraint + @NotEmpty(message = "Movie name cannot be empty.") private String name; - - @Size(min = 2, message = "Atleast 2 genres should be provided.") - private List genres; - - @NotNull(message = "Actor list cannot be null.") - @NotEmpty(message = "Actor list cannot be empty.") - private List actors; - - public Movie(String name, List genres, List actors) { + + public Movie(String name) { this.id = UUID.randomUUID() .toString(); this.name = name; - this.genres = genres; - this.actors = actors; } - + } From de91009dfee81bb548275fae4c989bc36396ecdc Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:29:22 +0530 Subject: [PATCH 04/14] Delete Actor.java --- .../listvalidation/model/Actor.java | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java deleted file mode 100644 index e6215f00c4..0000000000 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Actor.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.validation.listvalidation.model; - -import java.util.UUID; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@NoArgsConstructor -public class Actor { - - private String id; - private String name; - - public Actor(String name) { - this.id = UUID.randomUUID() - .toString(); - this.name = name; - } -} From ff21ddbe44d97c326d0ad2173579c7bb353a75dd Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:31:17 +0530 Subject: [PATCH 05/14] Delete MovieRepository.java --- .../repository/MovieRepository.java | 57 ------------------- 1 file changed, 57 deletions(-) delete mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java deleted file mode 100644 index 67cfa6daca..0000000000 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/repository/MovieRepository.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.baeldung.validation.listvalidation.repository; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Repository; - -import com.baeldung.validation.listvalidation.model.Actor; -import com.baeldung.validation.listvalidation.model.Movie; - -@Repository -public class MovieRepository { - private final Logger LOGGER = LoggerFactory.getLogger(MovieRepository.class); - static List moviesData; - - static { - moviesData = new ArrayList<>(); - - Actor a1 = new Actor("Actor1"); - - Movie m1 = new Movie("MovieABC", Arrays.asList("Drama"), Arrays.asList(a1)); - moviesData.add(m1); - - Movie m2 = new Movie("MovieDEF", Arrays.asList("Drama"), Arrays.asList(a1)); - moviesData.add(m2); - - } - - public void add(Movie movie) { - if (get(movie.getName()) == null) { - moviesData.add(movie); - LOGGER.info("Added new movie."); - } - } - - public Movie get(String name) { - Movie movie = null; - for (Movie m : moviesData) { - if (name.equalsIgnoreCase(m.getName())) { - movie = m; - LOGGER.info("Found movie with name " + name + ":" + movie); - } - } - - return movie; - } - - public void addAll(List movies) { - for (Movie movie : movies) { - add(movie); - } - } - -} From 99fd6d29a23566c897f19a44b777866b45cb6057 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:37:11 +0530 Subject: [PATCH 06/14] Create MovieService.java --- .../listvalidation/service/MovieService.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java new file mode 100644 index 0000000000..0339df595d --- /dev/null +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java @@ -0,0 +1,55 @@ +package com.baeldung.validation.listvalidation.service; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import com.baeldung.validation.listvalidation.model.Movie; + +@Service +public class MovieService { + + private final Logger logger = LoggerFactory.getLogger(MovieService.class); + + private static List moviesData; + + static { + moviesData = new ArrayList<>(); + + Movie m1 = new Movie("MovieABC"); + moviesData.add(m1); + + Movie m2 = new Movie("MovieDEF"); + moviesData.add(m2); + + } + + public Movie get(String name) { + Movie movie = null; + for (Movie m : moviesData) { + if (name.equalsIgnoreCase(m.getName())) { + movie = m; + logger.info("Found movie with name {} : {} ", name, movie); + } + } + + return movie; + } + + public void add(Movie movie) { + if (get(movie.getName()) == null) { + moviesData.add(movie); + logger.info("Added new movie - {}", movie.getName()); + } + } + + public void addAll(List movies) { + for (Movie movie : movies) { + add(movie); + } + } + +} From 90dc6c6d7aa90b2ae34531bf6a236554160a31b4 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:39:16 +0530 Subject: [PATCH 07/14] Update MovieController.java --- .../controller/MovieController.java | 41 ++++--------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java index 6265fd50d0..b8db850809 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java @@ -3,52 +3,29 @@ package com.baeldung.validation.listvalidation.controller; import java.util.List; import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; +import com.baeldung.validation.listvalidation.constraint.CustomConstraint; import com.baeldung.validation.listvalidation.model.Movie; -import com.baeldung.validation.listvalidation.repository.MovieRepository; +import com.baeldung.validation.listvalidation.service.MovieService; @Validated @RestController -@RequestMapping("/movie") +@RequestMapping("/movies") public class MovieController { - private final Logger LOGGER = LoggerFactory.getLogger(MovieController.class); - @Autowired - private MovieRepository movieRepository; + private MovieService movieService; - @RequestMapping(method = RequestMethod.POST) - public void add(@RequestBody @Valid Movie movie, BindingResult bindingResult) { - if (bindingResult.hasErrors()) { - StringBuilder builder = new StringBuilder(); - bindingResult.getAllErrors() - .forEach(error -> builder.append(" " + error.getDefaultMessage())); - LOGGER.error(builder.toString()); - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, bindingResult.toString()); - } - movieRepository.add(movie); - } - - @RequestMapping(value = "/batch", method = RequestMethod.POST) - public void addAll(@RequestBody List<@Valid Movie> movie) { - movieRepository.addAll(movie); - } - - @RequestMapping(method = RequestMethod.GET, value = "/{name}") - public Movie get(@PathVariable String name) throws Exception { - return movieRepository.get(name); + @PostMapping + public void addAll(@RequestBody @NotEmpty(message = "Input movie list cannot be empty.") @CustomConstraint List<@Valid Movie> movie) { + movieService.addAll(movie); } } From d9abb296b74b4d8eb8c4fd80ac6e67ad4baf55a7 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:40:38 +0530 Subject: [PATCH 08/14] Update CustomConstraint.java --- .../validation/listvalidation/constraint/CustomConstraint.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java index 5d6e2213f1..033df5a25b 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java @@ -10,7 +10,7 @@ import javax.validation.Payload; @Retention(RetentionPolicy.RUNTIME) public @interface CustomConstraint { - String message() default "Invalid movie name."; + String message() default "Movie name should start with an alphanumeric character."; Class[] groups() default {}; From a5f06318502750a5593578761cdbd7f3176554a3 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:42:36 +0530 Subject: [PATCH 09/14] Update CustomConstraintValidator.java --- .../constraint/CustomConstraintValidator.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java index 9f18a0c218..3e80a79afe 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java @@ -1,17 +1,32 @@ package com.baeldung.validation.listvalidation.constraint; +import java.util.List; +import java.util.regex.Pattern; + import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; -public class CustomConstraintValidator implements ConstraintValidator { +import com.baeldung.validation.listvalidation.model.Movie; + +public class CustomConstraintValidator implements ConstraintValidator> { @Override - public boolean isValid(String value, ConstraintValidatorContext context) { - if (value == null || value.isEmpty()) { - return false; - } else { - return true; + public boolean isValid(List values, ConstraintValidatorContext context) { + boolean isValid = true; + if (values == null || values.isEmpty()) { + isValid = false; + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate("Movie list cannot be empty.") + .addConstraintViolation(); } + String regex = "[^A-Za-z0-9].*"; + for (Movie movie : values) { + if (Pattern.matches(regex, movie.getName())) { + isValid = false; + break; + } + } + return isValid; } } From 077f38e318d6157777d978d503db158104e283c1 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:45:16 +0530 Subject: [PATCH 10/14] Update MovieControllerIntegrationTest.java --- .../MovieControllerIntegrationTest.java | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java b/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java index 226e609d5f..dd8685b54c 100644 --- a/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java +++ b/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java @@ -15,7 +15,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; -import com.baeldung.validation.listvalidation.model.Actor; import com.baeldung.validation.listvalidation.model.Movie; import com.fasterxml.jackson.databind.ObjectMapper; @@ -28,38 +27,47 @@ public class MovieControllerIntegrationTest { private MockMvc mvc; ObjectMapper objectMapper = new ObjectMapper(); - + @Test - public void given1Genre_whenAddingMovie_thenThrowBadRequest() throws Exception { - Actor actor = new Actor("Actor1"); - Movie movie = new Movie("Movie1", Arrays.asList("Drama"), Arrays.asList(actor)); - mvc.perform(MockMvcRequestBuilders.post("/movie") + public void givenValidMovieList_whenAddingMovieList_thenIsOK() throws Exception { + List movies = new ArrayList<>(); + Movie movie = new Movie("Movie3"); + movies.add(movie); + mvc.perform(MockMvcRequestBuilders.post("/movies") .contentType(MediaType.APPLICATION_JSON_UTF8) - .content(objectMapper.writeValueAsString(movie))) + .content(objectMapper.writeValueAsString(movies))) + .andExpect(MockMvcResultMatchers.status() + .isOk()); + } + + @Test + public void givenEmptyMovieList_whenAddingMovieList_thenThrowBadRequest() throws Exception { + List movies = new ArrayList<>(); + mvc.perform(MockMvcRequestBuilders.post("/movies") + .contentType(MediaType.APPLICATION_JSON_UTF8) + .content(objectMapper.writeValueAsString(movies))) .andExpect(MockMvcResultMatchers.status() .isBadRequest()); } - + @Test - public void givenWithoutActor_whenAddingMovieList_thenThrowBadRequest() throws Exception { - List actors = new ArrayList<>(); - Movie movie = new Movie("Movie2", Arrays.asList("Action", "Thriller"), actors); - mvc.perform(MockMvcRequestBuilders.post("/movie/batch") + public void givenEmptyMovieName_whenAddingMovieList_thenThrowBadRequest() throws Exception { + Movie movie = new Movie(""); + mvc.perform(MockMvcRequestBuilders.post("/movies") .contentType(MediaType.APPLICATION_JSON_UTF8) .content(objectMapper.writeValueAsString(Arrays.asList(movie)))) .andExpect(MockMvcResultMatchers.status() .isBadRequest()); } - + @Test - public void givenEmptyMovieName_whenAddingMovie_thenThrowBadRequest() throws Exception { - Actor actor = new Actor("Actor1"); - Movie movie = new Movie("", Arrays.asList("Drama", "History"), Arrays.asList(actor)); - mvc.perform(MockMvcRequestBuilders.post("/movie") + public void givenInvalidMovieName_whenAddingMovieList_thenThrowBadRequest() throws Exception { + Movie movie = new Movie("$Movie2"); + mvc.perform(MockMvcRequestBuilders.post("/movies") .contentType(MediaType.APPLICATION_JSON_UTF8) - .content(objectMapper.writeValueAsString(movie))) + .content(objectMapper.writeValueAsString(Arrays.asList(movie)))) .andExpect(MockMvcResultMatchers.status() .isBadRequest()); } - + } From b3af5e65b701683cd602345fe248e5541974abe7 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Sat, 10 Aug 2019 14:58:43 +0530 Subject: [PATCH 11/14] 3005 | updated custom constraint and test case * Create MaxSizeConstraint.java * Delete CustomConstraintValidator.java * Delete CustomConstraint.java * Create MaxSizeConstraintValidator.java * Update MovieController.java * Update MovieControllerIntegrationTest.java --- ...tomConstraint.java => MaxSizeConstraint.java} | 10 +++++----- ...ator.java => MaxSizeConstraintValidator.java} | 14 ++++---------- .../controller/MovieController.java | 6 +++--- .../MovieControllerIntegrationTest.java | 16 +++++++++++++--- 4 files changed, 25 insertions(+), 21 deletions(-) rename spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/{CustomConstraint.java => MaxSizeConstraint.java} (64%) rename spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/{CustomConstraintValidator.java => MaxSizeConstraintValidator.java} (65%) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java similarity index 64% rename from spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java rename to spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java index 033df5a25b..b5adab5d86 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraint.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java @@ -6,13 +6,13 @@ import java.lang.annotation.RetentionPolicy; import javax.validation.Constraint; import javax.validation.Payload; -@Constraint(validatedBy = CustomConstraintValidator.class) +@Constraint(validatedBy = MaxSizeConstraintValidator.class) @Retention(RetentionPolicy.RUNTIME) -public @interface CustomConstraint { - - String message() default "Movie name should start with an alphanumeric character."; +public @interface MaxSizeConstraint { + String message() default "The input list cannot contain more than 4 movies."; + Class[] groups() default {}; - + Class[] payload() default {}; } diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java similarity index 65% rename from spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java rename to spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java index 3e80a79afe..813ea3e657 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/CustomConstraintValidator.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java @@ -1,14 +1,13 @@ package com.baeldung.validation.listvalidation.constraint; import java.util.List; -import java.util.regex.Pattern; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import com.baeldung.validation.listvalidation.model.Movie; -public class CustomConstraintValidator implements ConstraintValidator> { +public class MaxSizeConstraintValidator implements ConstraintValidator> { @Override public boolean isValid(List values, ConstraintValidatorContext context) { @@ -18,15 +17,10 @@ public class CustomConstraintValidator implements ConstraintValidator 4) { + isValid = false; } return isValid; } - + } diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java index b8db850809..45639cf303 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.baeldung.validation.listvalidation.constraint.CustomConstraint; +import com.baeldung.validation.listvalidation.constraint.MaxSizeConstraint; import com.baeldung.validation.listvalidation.model.Movie; import com.baeldung.validation.listvalidation.service.MovieService; @@ -25,7 +25,7 @@ public class MovieController { private MovieService movieService; @PostMapping - public void addAll(@RequestBody @NotEmpty(message = "Input movie list cannot be empty.") @CustomConstraint List<@Valid Movie> movie) { - movieService.addAll(movie); + public void addAll(@RequestBody @NotEmpty(message = "Input movie list cannot be empty.") @MaxSizeConstraint List<@Valid Movie> movies) { + movieService.addAll(movies); } } diff --git a/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java b/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java index dd8685b54c..cddc6c6bd9 100644 --- a/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java +++ b/spring-mvc-simple-2/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java @@ -61,11 +61,21 @@ public class MovieControllerIntegrationTest { } @Test - public void givenInvalidMovieName_whenAddingMovieList_thenThrowBadRequest() throws Exception { - Movie movie = new Movie("$Movie2"); + public void given5MoviesInputList_whenAddingMovieList_thenThrowBadRequest() throws Exception { + Movie movie1 = new Movie("Movie1"); + Movie movie2 = new Movie("Movie2"); + Movie movie3 = new Movie("Movie3"); + Movie movie4 = new Movie("Movie4"); + Movie movie5 = new Movie("Movie5"); + List movies = new ArrayList<>(); + movies.add(movie1); + movies.add(movie2); + movies.add(movie3); + movies.add(movie4); + movies.add(movie5); mvc.perform(MockMvcRequestBuilders.post("/movies") .contentType(MediaType.APPLICATION_JSON_UTF8) - .content(objectMapper.writeValueAsString(Arrays.asList(movie)))) + .content(objectMapper.writeValueAsString(movies))) .andExpect(MockMvcResultMatchers.status() .isBadRequest()); } From 28e18be37aa125f89ff2d9aa382be66bbc276c50 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Mon, 12 Aug 2019 03:55:13 +0530 Subject: [PATCH 12/14] Update MaxSizeConstraintValidator.java --- .../constraint/MaxSizeConstraintValidator.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java index 813ea3e657..0154fb636a 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java @@ -12,15 +12,10 @@ public class MaxSizeConstraintValidator implements ConstraintValidator values, ConstraintValidatorContext context) { boolean isValid = true; - if (values == null || values.isEmpty()) { - isValid = false; - context.disableDefaultConstraintViolation(); - context.buildConstraintViolationWithTemplate("Movie list cannot be empty.") - .addConstraintViolation(); - } else if (values.size() > 4) { + if (values.size() > 4) { isValid = false; } return isValid; } - + } From 8b68e172349ec77272dad7c11eaac5d0051e23dc Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Sun, 18 Aug 2019 02:55:55 +0530 Subject: [PATCH 13/14] Update Movie.java --- .../listvalidation/model/Movie.java | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java index 035c5f4412..f5a49877bf 100644 --- a/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java +++ b/spring-mvc-simple-2/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java @@ -4,13 +4,6 @@ import java.util.UUID; import javax.validation.constraints.NotEmpty; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -@NoArgsConstructor public class Movie { private String id; @@ -23,5 +16,25 @@ public class Movie { .toString(); this.name = name; } - + + public Movie(){ + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } From d4b8f8696532b3a19e1a5abfb707757d1d9f5263 Mon Sep 17 00:00:00 2001 From: Pallavi Priyadarshani <50460471+pallavi-priyadarshani@users.noreply.github.com> Date: Sun, 18 Aug 2019 03:05:51 +0530 Subject: [PATCH 14/14] Update pom.xml --- spring-mvc-simple-2/pom.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/spring-mvc-simple-2/pom.xml b/spring-mvc-simple-2/pom.xml index 2fe93f1fae..74302cff78 100644 --- a/spring-mvc-simple-2/pom.xml +++ b/spring-mvc-simple-2/pom.xml @@ -18,10 +18,6 @@ org.springframework.boot spring-boot-starter-web - - org.projectlombok - lombok -