diff --git a/spring-mvc-java/pom.xml b/spring-mvc-java/pom.xml index ef18cef3e0..0f6dbfbd98 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-mvc-java/pom.xml @@ -166,7 +166,28 @@ poi-ooxml ${poi.version} - + + + + javax.validation + validation-api + 1.1.0.Final + + + org.hibernate + hibernate-validator + 5.1.2.Final + + + javax.el + javax.el-api + 2.2.4 + + + org.glassfish.web + javax.el + 2.2.4 + diff --git a/spring-mvc-java/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java new file mode 100644 index 0000000000..2fba2720c3 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java @@ -0,0 +1,22 @@ +package com.baeldung.customvalidator; + +import java.lang.annotation.Documented; +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; + +@Documented +@Constraint(validatedBy = ContactNumberValidator.class) +@Target( { ElementType.METHOD, ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ContactNumberConstraint { + + String message() default "Invalid phone number"; + Class[] groups() default {}; + Class[] payload() default {}; + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java new file mode 100644 index 0000000000..a7eb7a9df4 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java @@ -0,0 +1,19 @@ +package com.baeldung.customvalidator; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class ContactNumberValidator implements ConstraintValidator { + + @Override + public void initialize(ContactNumberConstraint contactNumber) {} + + @Override + public boolean isValid(String contactField, ConstraintValidatorContext cxt) { + if(contactField == null) { + return false; + } + return contactField.matches("[0-9]+") && (contactField.length() > 8) && (contactField.length() < 14); + } + +} diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/ValidatedPhone.java b/spring-mvc-java/src/main/java/com/baeldung/model/ValidatedPhone.java new file mode 100644 index 0000000000..f860394707 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/model/ValidatedPhone.java @@ -0,0 +1,18 @@ +package com.baeldung.model; + +import com.baeldung.customvalidator.ContactNumberConstraint; + +public class ValidatedPhone { + + @ContactNumberConstraint + private String phone; + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + +} 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 new file mode 100644 index 0000000000..70b151e066 --- /dev/null +++ b/spring-mvc-java/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java @@ -0,0 +1,35 @@ +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.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import com.baeldung.model.ValidatedPhone; + +@Controller +@EnableWebMvc +public class ValidatedPhoneController { + + @RequestMapping(value="/validatePhone", method=RequestMethod.GET) + public String loadFormPage(Model m) { + m.addAttribute("validatedPhone", new ValidatedPhone()); + return "phoneHome"; + } + + @RequestMapping(value="/addValidatePhone", method=RequestMethod.POST) + public String submitForm(@Valid ValidatedPhone validatedPhone, BindingResult result, Model m) { + if(result.hasErrors()) { + return "phoneHome"; + } + + m.addAttribute("message", "Successfully saved phone: " + validatedPhone.toString()); + return "phoneHome"; + } + + +} diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml index 4ba9642448..b0a4d4892a 100644 --- a/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml +++ b/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -1,6 +1,14 @@ - - + + + \ No newline at end of file diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/phoneHome.jsp b/spring-mvc-java/src/main/webapp/WEB-INF/view/phoneHome.jsp new file mode 100644 index 0000000000..b873e9bc5f --- /dev/null +++ b/spring-mvc-java/src/main/webapp/WEB-INF/view/phoneHome.jsp @@ -0,0 +1,38 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> + + + + + Sample Form + + + + +
+ +

Phone Number

+
${message}
+ + + + + + +
+ + +
+
+ + diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/CustomMVCValidatorTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/CustomMVCValidatorTest.java new file mode 100644 index 0000000000..069cc8e141 --- /dev/null +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/CustomMVCValidatorTest.java @@ -0,0 +1,41 @@ +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 CustomMVCValidatorTest { + + private MockMvc mockMvc; + + @Before + public void setup(){ + this.mockMvc = MockMvcBuilders.standaloneSetup(new ValidatedPhoneController()).build(); + } + + @Test + public void givenPhonePageUri_whenMockMvc_thenReturnsPhonePage() throws Exception{ + this.mockMvc.perform(get("/validatePhone")).andExpect(view().name("phoneHome")); + } + + @Test + public void givenPhoneURIWithPostAndFormData_whenMockMVC_thenVerifyErrorResponse() throws Exception { + this.mockMvc.perform(MockMvcRequestBuilders.post("/addValidatePhone"). + accept(MediaType.TEXT_HTML). + param("phoneInput", "123")). + andExpect(model().attributeHasFieldErrorCode("validatedPhone", "phone","ContactNumberConstraint")). + andExpect(view().name("phoneHome")). + andExpect(status().isOk()). + andDo(print()); + } + +}