Moved MVC Custom Valitation article code from spring-mvc-java to spring-mvc-basics module

This commit is contained in:
Gerardo Roza 2019-07-01 19:35:33 -03:00
parent e84ea4d4c5
commit e77faf8d99
13 changed files with 207 additions and 207 deletions

View File

@ -12,4 +12,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [A Guide to the ViewResolver in Spring MVC](http://www.baeldung.com/spring-mvc-view-resolver-tutorial) - [A Guide to the ViewResolver in Spring MVC](http://www.baeldung.com/spring-mvc-view-resolver-tutorial)
- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings) - [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings)
- [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml) - [Spring MVC Content Negotiation](http://www.baeldung.com/spring-mvc-content-negotiation-json-xml)
- [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts) - [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts)
- [Spring MVC Custom Validation](http://www.baeldung.com/spring-mvc-custom-validator)

View File

@ -1,24 +1,24 @@
package com.baeldung.customvalidator; package com.baeldung.customvalidator;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import javax.validation.Constraint; import javax.validation.Constraint;
import javax.validation.Payload; import javax.validation.Payload;
@Documented @Documented
@Constraint(validatedBy = ContactNumberValidator.class) @Constraint(validatedBy = ContactNumberValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD}) @Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface ContactNumberConstraint { public @interface ContactNumberConstraint {
String message() default "Invalid phone number"; String message() default "Invalid phone number";
Class<?>[] groups() default {}; Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {}; Class<? extends Payload>[] payload() default {};
} }

View File

@ -1,17 +1,17 @@
package com.baeldung.customvalidator; package com.baeldung.customvalidator;
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintValidatorContext;
public class ContactNumberValidator implements ConstraintValidator<ContactNumberConstraint, String> { public class ContactNumberValidator implements ConstraintValidator<ContactNumberConstraint, String> {
@Override @Override
public void initialize(ContactNumberConstraint contactNumber) { public void initialize(ContactNumberConstraint contactNumber) {
} }
@Override @Override
public boolean isValid(String contactField, ConstraintValidatorContext cxt) { public boolean isValid(String contactField, ConstraintValidatorContext cxt) {
return contactField != null && contactField.matches("[0-9]+") && (contactField.length() > 8) && (contactField.length() < 14); return contactField != null && contactField.matches("[0-9]+") && (contactField.length() > 8) && (contactField.length() < 14);
} }
} }

View File

@ -2,10 +2,7 @@ package com.baeldung.model;
import com.baeldung.customvalidator.FieldsValueMatch; import com.baeldung.customvalidator.FieldsValueMatch;
@FieldsValueMatch.List({ @FieldsValueMatch.List({ @FieldsValueMatch(field = "password", fieldMatch = "verifyPassword", message = "Passwords do not match!"), @FieldsValueMatch(field = "email", fieldMatch = "verifyEmail", message = "Email addresses do not match!") })
@FieldsValueMatch(field = "password", fieldMatch = "verifyPassword", message = "Passwords do not match!"),
@FieldsValueMatch(field = "email", fieldMatch = "verifyEmail", message = "Email addresses do not match!")
})
public class NewUserForm { public class NewUserForm {
private String email; private String email;
private String verifyEmail; private String verifyEmail;

View File

@ -1,22 +1,22 @@
package com.baeldung.model; package com.baeldung.model;
import com.baeldung.customvalidator.ContactNumberConstraint; import com.baeldung.customvalidator.ContactNumberConstraint;
public class ValidatedPhone { public class ValidatedPhone {
@ContactNumberConstraint @ContactNumberConstraint
private String phone; private String phone;
public String getPhone() { public String getPhone() {
return phone; return phone;
} }
public void setPhone(String phone) { public void setPhone(String phone) {
this.phone = phone; this.phone = phone;
} }
@Override @Override
public String toString() { public String toString() {
return phone; return phone;
} }
} }

View File

@ -1,32 +1,32 @@
package com.baeldung.web.controller; package com.baeldung.web.controller;
import com.baeldung.model.ValidatedPhone; import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.validation.Valid;
import com.baeldung.model.ValidatedPhone;
@Controller
public class ValidatedPhoneController { @Controller
public class ValidatedPhoneController {
@GetMapping("/validatePhone")
public String loadFormPage(Model m) { @GetMapping("/validatePhone")
m.addAttribute("validatedPhone", new ValidatedPhone()); public String loadFormPage(Model m) {
return "phoneHome"; m.addAttribute("validatedPhone", new ValidatedPhone());
} return "phoneHome";
}
@PostMapping("/addValidatePhone")
public String submitForm(@Valid ValidatedPhone validatedPhone, BindingResult result, Model m) { @PostMapping("/addValidatePhone")
if (result.hasErrors()) { public String submitForm(@Valid ValidatedPhone validatedPhone, BindingResult result, Model m) {
return "phoneHome"; if (result.hasErrors()) {
} return "phoneHome";
}
m.addAttribute("message", "Successfully saved phone: " + validatedPhone.toString());
return "phoneHome"; m.addAttribute("message", "Successfully saved phone: " + validatedPhone.toString());
} return "phoneHome";
}
} }

View File

@ -1,38 +1,38 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<title>Sample Form</title> <title>Sample Form</title>
<style> <style>
body { background-color: #eee; font: helvetica; } body { background-color: #eee; font: helvetica; }
#container { width: 500px; background-color: #fff; margin: 30px auto; padding: 30px; border-radius: 5px; } #container { width: 500px; background-color: #fff; margin: 30px auto; padding: 30px; border-radius: 5px; }
.green { font-weight: bold; color: green; } .green { font-weight: bold; color: green; }
.message { margin-bottom: 10px; } .message { margin-bottom: 10px; }
label {width:70px; display:inline-block;} label {width:70px; display:inline-block;}
input { display:inline-block; margin-right: 10px; } input { display:inline-block; margin-right: 10px; }
form {line-height: 160%; } form {line-height: 160%; }
.hide { display: none; } .hide { display: none; }
.error { color: red; font-size: 0.9em; font-weight: bold; } .error { color: red; font-size: 0.9em; font-weight: bold; }
</style> </style>
</head> </head>
<body> <body>
<div id="container"> <div id="container">
<h2>Phone Number</h2> <h2>Phone Number</h2>
<c:if test="${not empty message}"><div class="message green">${message}</div></c:if> <c:if test="${not empty message}"><div class="message green">${message}</div></c:if>
<form:form action="/spring-mvc-java/addValidatePhone" modelAttribute="validatedPhone"> <form:form action="/spring-mvc-basics/addValidatePhone" modelAttribute="validatedPhone">
<label for="phoneInput">Phone: </label> <label for="phoneInput">Phone: </label>
<form:input path="phone" id="phoneInput" /> <form:input path="phone" id="phoneInput" />
<form:errors path="phone" cssClass="error" /> <form:errors path="phone" cssClass="error" />
<br/> <br/>
<input type="submit" value="Submit" /> <input type="submit" value="Submit" />
</form:form> </form:form>
</div> </div>
</body> </body>
</html> </html>

View File

@ -5,46 +5,47 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.Before; import org.junit.jupiter.api.BeforeEach;
import org.junit.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class ClassValidationMvcIntegrationTest { public class ClassValidationMvcIntegrationTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Before @BeforeEach
public void setup(){ public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new NewUserController()).build(); this.mockMvc = MockMvcBuilders.standaloneSetup(new NewUserController())
.build();
} }
@Test @Test
public void givenMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception { public void givenMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/user") this.mockMvc.perform(MockMvcRequestBuilders.post("/user")
.accept(MediaType.TEXT_HTML) .accept(MediaType.TEXT_HTML)
.param("email", "john@yahoo.com") .param("email", "john@yahoo.com")
.param("verifyEmail", "john@yahoo.com") .param("verifyEmail", "john@yahoo.com")
.param("password", "pass") .param("password", "pass")
.param("verifyPassword", "pass")) .param("verifyPassword", "pass"))
.andExpect(model().attribute("message", "Valid form")) .andExpect(model().attribute("message", "Valid form"))
.andExpect(view().name("userHome")) .andExpect(view().name("userHome"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andDo(print()); .andDo(print());
} }
@Test @Test
public void givenNotMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception { public void givenNotMatchingEmailPassword_whenPostNewUserForm_thenOk() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/user") this.mockMvc.perform(MockMvcRequestBuilders.post("/user")
.accept(MediaType.TEXT_HTML) .accept(MediaType.TEXT_HTML)
.param("email", "john@yahoo.com") .param("email", "john@yahoo.com")
.param("verifyEmail", "john@yahoo.commmm") .param("verifyEmail", "john@yahoo.commmm")
.param("password", "pass") .param("password", "pass")
.param("verifyPassword", "passsss")) .param("verifyPassword", "passsss"))
.andExpect(model().errorCount(2)) .andExpect(model().errorCount(2))
.andExpect(view().name("userHome")) .andExpect(view().name("userHome"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andDo(print()); .andDo(print());
} }
} }

View File

@ -1,41 +1,43 @@
package com.baeldung.web.controller; package com.baeldung.web.controller;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 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.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 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.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.Before; import org.junit.jupiter.api.BeforeEach;
import org.junit.Test; import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
public class CustomMVCValidatorIntegrationTest { public class CustomMVCValidatorIntegrationTest {
private MockMvc mockMvc; private MockMvc mockMvc;
@Before @BeforeEach
public void setup(){ public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new ValidatedPhoneController()).build(); this.mockMvc = MockMvcBuilders.standaloneSetup(new ValidatedPhoneController())
} .build();
}
@Test
public void givenPhonePageUri_whenMockMvc_thenReturnsPhonePage() throws Exception{ @Test
this.mockMvc.perform(get("/validatePhone")).andExpect(view().name("phoneHome")); 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"). @Test
accept(MediaType.TEXT_HTML). public void givenPhoneURIWithPostAndFormData_whenMockMVC_thenVerifyErrorResponse() throws Exception {
param("phoneInput", "123")). this.mockMvc.perform(MockMvcRequestBuilders.post("/addValidatePhone")
andExpect(model().attributeHasFieldErrorCode("validatedPhone", "phone","ContactNumberConstraint")). .accept(MediaType.TEXT_HTML)
andExpect(view().name("phoneHome")). .param("phoneInput", "123"))
andExpect(status().isOk()). .andExpect(model().attributeHasFieldErrorCode("validatedPhone", "phone", "ContactNumberConstraint"))
andDo(print()); .andExpect(view().name("phoneHome"))
} .andExpect(status().isOk())
.andDo(print());
} }
}

View File

@ -16,7 +16,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Circular Dependencies in Spring](http://www.baeldung.com/circular-dependencies-in-spring) - [Circular Dependencies in Spring](http://www.baeldung.com/circular-dependencies-in-spring)
- [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit) - [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit)
- [Upload and Display Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files) - [Upload and Display Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files)
- [Spring MVC Custom Validation](http://www.baeldung.com/spring-mvc-custom-validator)
- [web.xml vs Initializer with Spring](http://www.baeldung.com/spring-xml-vs-java-config) - [web.xml vs Initializer with Spring](http://www.baeldung.com/spring-xml-vs-java-config)
- [The HttpMediaTypeNotAcceptableException in Spring MVC](http://www.baeldung.com/spring-httpmediatypenotacceptable) - [The HttpMediaTypeNotAcceptableException in Spring MVC](http://www.baeldung.com/spring-httpmediatypenotacceptable)
- [Spring MVC and the @ModelAttribute Annotation](http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation) - [Spring MVC and the @ModelAttribute Annotation](http://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation)