From 35042964b6c1269d13ac1f1c6f2acdc0c547e5c0 Mon Sep 17 00:00:00 2001 From: lor6 Date: Sun, 14 May 2017 00:14:55 +0300 Subject: [PATCH] custom class validation (#1832) * custom class validation * formatting --- .../customvalidator/FieldsValueMatch.java | 31 ++++++++++ .../FieldsValueMatchValidator.java | 31 ++++++++++ .../java/com/baeldung/model/NewUserForm.java | 58 +++++++++++++++++++ .../web/controller/NewUserController.java | 31 ++++++++++ .../controller/ValidatedPhoneController.java | 2 - .../controller/ClassValidationMvcTest.java | 51 ++++++++++++++++ 6 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java create mode 100644 spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java create mode 100644 spring-mvc-java/src/main/java/com/baeldung/model/NewUserForm.java create mode 100644 spring-mvc-java/src/main/java/com/baeldung/web/controller/NewUserController.java create mode 100644 spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcTest.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java new file mode 100644 index 0000000000..51db279f0b --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java @@ -0,0 +1,31 @@ +package com.baeldung.customvalidator; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + +@Constraint(validatedBy = FieldsValueMatchValidator.class) +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface FieldsValueMatch { + + String message() default "Fields values don't match!"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + String field(); + + String fieldMatch(); + + @Target({ ElementType.TYPE }) + @Retention(RetentionPolicy.RUNTIME) + @interface List { + FieldsValueMatch[] value(); + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java new file mode 100644 index 0000000000..c3e8533ec9 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java @@ -0,0 +1,31 @@ +package com.baeldung.customvalidator; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.springframework.beans.BeanWrapperImpl; + +public class FieldsValueMatchValidator implements ConstraintValidator { + + private String field; + private String fieldMatch; + + public void initialize(FieldsValueMatch constraintAnnotation) { + this.field = constraintAnnotation.field(); + this.fieldMatch = constraintAnnotation.fieldMatch(); + } + + public boolean isValid(Object value, ConstraintValidatorContext context) { + + Object fieldValue = new BeanWrapperImpl(value).getPropertyValue(field); + Object fieldMatchValue = new BeanWrapperImpl(value).getPropertyValue(fieldMatch); + + if (fieldValue != null) { + return fieldValue.equals(fieldMatchValue); + } else { + return fieldMatchValue == null; + } + + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/NewUserForm.java b/spring-mvc-java/src/main/java/com/baeldung/model/NewUserForm.java new file mode 100644 index 0000000000..12969b6002 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/NewUserForm.java @@ -0,0 +1,58 @@ +package com.baeldung.model; + +import com.baeldung.customvalidator.FieldsValueMatch; + +@FieldsValueMatch.List({ + @FieldsValueMatch(field = "password", fieldMatch = "verifyPassword", message = "Passwords do not match!"), + @FieldsValueMatch(field = "email", fieldMatch = "verifyEmail", message = "Email addresses do not match!") +}) +public class NewUserForm { + private String email; + private String verifyEmail; + private String password; + private String verifyPassword; + + public NewUserForm() { + } + + public NewUserForm(String email, String verifyEmail, String password, String verifyPassword) { + super(); + this.email = email; + this.verifyEmail = verifyEmail; + this.password = password; + this.verifyPassword = verifyPassword; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getVerifyEmail() { + return verifyEmail; + } + + public void setVerifyEmail(String verifyEmail) { + this.verifyEmail = verifyEmail; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getVerifyPassword() { + return verifyPassword; + } + + public void setVerifyPassword(String verifyPassword) { + this.verifyPassword = verifyPassword; + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/NewUserController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/NewUserController.java new file mode 100644 index 0000000000..fddd8baabb --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/NewUserController.java @@ -0,0 +1,31 @@ +package com.baeldung.web.controller; + +import javax.validation.Valid; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; + +import com.baeldung.model.NewUserForm; + +@Controller +public class NewUserController { + + @GetMapping("/user") + public String loadFormPage(Model model) { + model.addAttribute("newUserForm", new NewUserForm()); + return "userHome"; + } + + @PostMapping("/user") + public String submitForm(@Valid NewUserForm newUserForm, BindingResult result, Model model) { + if (result.hasErrors()) { + return "userHome"; + } + + model.addAttribute("message", "Valid form"); + return "userHome"; + } +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java index 8c6cfcd3be..9b3a6b3a4c 100644 --- a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java @@ -6,12 +6,10 @@ import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; import javax.validation.Valid; @Controller -@EnableWebMvc public class ValidatedPhoneController { @GetMapping("/validatePhone") diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcTest.java new file mode 100644 index 0000000000..7a3317df06 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/ClassValidationMvcTest.java @@ -0,0 +1,51 @@ +package com.baeldung.web.controller; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +public class ClassValidationMvcTest { + private MockMvc mockMvc; + + @Before + public void setup(){ + this.mockMvc = MockMvcBuilders.standaloneSetup(new NewUserController()).build(); + } + + @Test + public void givenMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/user") + .accept(MediaType.TEXT_HTML) + .param("email", "john@yahoo.com") + .param("verifyEmail", "john@yahoo.com") + .param("password", "pass") + .param("verifyPassword", "pass")) + .andExpect(model().attribute("message", "Valid form")) + .andExpect(view().name("userHome")) + .andExpect(status().isOk()) + .andDo(print()); + } + + @Test + public void givenNotMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/user") + .accept(MediaType.TEXT_HTML) + .param("email", "john@yahoo.com") + .param("verifyEmail", "john@yahoo.commmm") + .param("password", "pass") + .param("verifyPassword", "passsss")) + .andExpect(model().errorCount(2)) + .andExpect(view().name("userHome")) + .andExpect(status().isOk()) + .andDo(print()); + } +}