In my spring MVC validation, the order of my error messages changes randomly, I would like the messages to be in the same order as they appear on the page.
My AccountForm.java class looks like:
@NotNull(message = "Account name cannot be empty.")
@Size(min=3, max=50, message="Account name must be between 3 and 50 characters long.")
private String accountName;
@NotNull(message = "Company name cannot be empty.")
@Size(min=3, max=50, message="Company name must be between 3 and 50 characters long.")
private String companyName;
And I also append some custom errors in my controller:
public ModelAndView create(@Valid AccountForm accountForm, BindingResult bindingResult) {
ModelAndView mav = new ModelAndView("accounts/new");
mav.addObject("errors", bindingResult.getAllErrors());
mav.addObject("accountForm", accountForm);
if (!bindingResult.hasErrors()) {
if(accountService.findByAccountName(accountForm.getAccountName()) != null) {
bindingResult.addError(new ObjectError("accountName", "Account name is already is use"));
}
..
..
}
if(bindingResult.hasErrors() {
return mav;
}
..
When I hit submit on the form, the order of the messages keeps changing.
I render the errors in my view using:
<#list errors as error>
<li>${error.defaultMessage}</li>
</#list>
Can this be fixed?
This is achieved via Validation Groups and Spring supportes it. You are using @Valid annotation, but it should have been @Validated in order to use Validation Groups:
public ModelAndView submitSearch(@Validated(value={OrderChecks.class}) @ModelAttribute("SearchStringBackingObject") final SearchStringBackingObject backingObject
OrderChecks.class:
@GroupSequence(value={NotEmptyGroup.class, LengthCheckGroup.class, DiacriticeCheckGroup.class, EmailValidationGroup.class, EmailLengthValidationGroup.class,
Email3EntriesValidationGroup.class, EntityAlreadyExistsValidatorGroup.class, Default.class})
public interface OrderChecks {}
And inside the backing Object:
@NotBlank(groups=NotEmptyGroup.class)
@Length(max=25, groups=LengthCheckGroup.class)
@DiacriticeCheck(groups=DiacriticeCheckGroup.class)
private String firstname="";
where each of the Entries in the @GroupSequence is an interface.
EDIT
So if you want the account name to be validated first, then you create an interface for it:
public interface AccountNameGroup{}
Then inside the Validation Group interface you this is going to be the first interface:
@GroupSequence(value={AccountNameGroup.class, the rest of groups})
public interface OrderOfGroups{}
And of course inside the Controller you specify the @Validated annotation with the OrderOFGroups interface.
In this way the Account Name will be validated first
I also faced the same issue and tried a lot. I think there is now standard way of doing this in JSR-303.
This can be achieved using groups (which I personally dont like) or by defining <form:error>
is desired sequence.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With