Moved MVC Custom Valitation article code from spring-mvc-java to spring-mvc-basics module
This commit is contained in:
parent
e84ea4d4c5
commit
e77faf8d99
@ -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)
|
@ -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 {};
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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>
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user