Reputation: 55
i am practicing validation in spring boot and i got a problem
This is my model:
public class Student {
@NotEmpty
@NotNull
@Length(min = 3, max = 10)
private String username;
@NotEmpty
@Pattern(regexp = "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})")
private String password;
@NotEmpty
@Email
private String email;
@URL
private String website;
@Min(18)
@Max(30)
private int age;
public Student() {
super();
}
public Student(String username, String password, String email, String website, int age) {
super();
this.username = username;
this.password = password;
this.email = email;
this.website = website;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getWebsite() {
return website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student [username=" + username + ", password=" + password + ", email=" + email + ", website=" + website
+ ", age=" + age + "]";
}
}
What i want to do is, when i validate this student class with a form, i want the @NotEmpty is the only error message to print if @NotEmpty is triggered, if @NotEmpty does not trigger, the other validation can freely print the error message, that mean when i leave the form blank, the field with @NotEmpty only print @NotEmpty error message, so i come up with an idea, that is modifying the bindingResult in the controller:
@Controller
@RequestMapping({ "validation", "" })
public class ValidationController {
@RequestMapping(value = { "index1", "/" }, method = RequestMethod.GET)
public String index(ModelMap modelMap) {
modelMap.put("student", new Student());
return "/validation/index";
}
@RequestMapping(value = { "resgister" }, method = RequestMethod.POST)
public String resgister(ModelMap modelMap, RedirectAttributes redirectAttributes, @ModelAttribute("student") @Valid Student student, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
var errors = Helper.customErrorMessageOrder(bindingResult.getFieldErrors());
bindingResult = new BeanPropertyBindingResult(student, "student");
for(var e : errors) {
bindingResult.addError(e);
}
return "/validation/index";
}
redirectAttributes.addFlashAttribute("message", "Success");
return "redirect:/validation/index1";
}
}
So good so far, i have successfully modify the bindingResult, i even print all the errors to check it out, and it work.
But when i leave the form blank and submit, it print all the errors, for example: the username field will print @NotEmpty and @Length(min = 3, max = 10) error messages, what i expect is only @NotEmpty can print the error message, i kinda have no idea why this happen, please help :(
My customErrorMessageOrder:
public static List<FieldError> customErrorMessageOrder(List<FieldError> listErrors){
var notEmptyListErrors = listErrors
.stream()
.filter(e -> e.getCode().equals("NotEmpty"))
.collect(Collectors.toList());
if(notEmptyListErrors.size()==0) {
return listErrors;
}
var alterListErrors = listErrors.stream().collect(Collectors.toList());
var newListErrors = notEmptyListErrors;
for(var e : notEmptyListErrors) {
alterListErrors.removeIf(e1->e1.getField().equals(e.getField()));
}
newListErrors.addAll(alterListErrors);
return newListErrors;
}
And my form, i use thymeleaf:
<form th:action="@{/validation/resgister}" method="post" th:object="${student}">
<table border="1">
<tr>
<td>Username</td>
<td><input type="text" th:field="*{username}"></td>
<td th:if="${#fields.hasErrors('username')}">
<span th:errors="*{username}"></span>
</td>
</tr>
<tr>
<td>Password</td>
<td><input type="text" th:field="*{password}"></td>
<td th:if="${#fields.hasErrors('password')}">
<span th:errors="*{password}"></span>
</td>
</tr>
<tr>
<td>Email</td>
<td><input type="text" th:field="*{email}"></td>
<td th:if="${#fields.hasErrors('email')}">
<span th:errors="*{email}"></span>
</td>
</tr>
<tr>
<td>Website</td>
<td><input type="text" th:field="*{website}"></td>
<td th:if="${#fields.hasErrors('website')}">
<span th:errors="*{website}"></span>
</td>
</tr>
<tr>
<td>Age</td>
<td><input type="text" th:field="*{age}"></td>
<td th:if="${#fields.hasErrors('age')}">
<span th:errors="*{age}"></span>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;"><input type="submit" value="submit"></td>
</tr>
</table>
</form>
Upvotes: 0
Views: 69
Reputation: 55
i got it, since bindingResult got auto pass to an key called:
org.springframework.validation.BindingResult.**<NAME_OF_MODEL_ATTRIBUTE>**
in thymeleaf, so i have to overwrite it in the controller:
modelMap.put("org.springframework.validation.BindingResult.student", bindingResult);
and it worked!!
Upvotes: 0