Spring Boot - not getting a validation errors - spring

I'm trying to validate the form. Spring correctly validates, but when errors should be returned, it receives an exception:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'employee' available as request attribute
Add I don't know what is wrong. Could you help me?
Controller:
#RequestMapping(value = "/employee/add",method = RequestMethod.POST)
public String addEmployee(#Valid DTOEmployee dtoEmployee, BindingResult result) {
if (result.hasErrors()) {
return "employee_add";
}
employeeService.save(dtoEmployee);
return "redirect:/employee?add";
}
DTOEmployee:
public class DTOEmployee{
#NotNull
private String name;
#NotNull
private String subname;
#NotNull
private String email;
}
fragments of employee_add:
<form th:action="#{/employee/add}" th:object="${employee}" method="post" class="form-inline justify-content-center">
<div class="input-group my-1">
<input th:field="*{name}" type="text" id="name" class="form-control"
placeholder="Your name"/>
<p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Name error</p>
<input th:field="*{subname}" type="text" id="name" class="form-control"
placeholder="Your subname"/>
<p th:if="${#fields.hasErrors('subname')}" th:errors="*{name}">Name error</p>
<input th:field="*{email}" type="email" id="email" class="form-control"
placeholder="Your mail"/>
<p th:if="${#fields.hasErrors('email')}" th:errors="*{email}">Name error</p>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
messages.properties:
NotNull.DTOEmployee.name = Name must be not null
NotNull.DTOEmployee.subname= Subname must be not null
NotNull.DTOEmployee.email= Email must be not null

Seems like you are mixing thymeleaf form submission with requests. As stated in the example from spring.io https://spring.io/guides/gs/handling-form-submission/
#PostMapping("/greeting")
public String greetingSubmit(#ModelAttribute Greeting greeting) {
return "result";
}
Seems you are missing #ModelAttribute

Hmmm... I`m added #ModelAttribute [ public String addEmployee(#Valid #ModelAttribute DTOEmployee dtoEmployee, BindingResult result)] and I get the following exception:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "employee_add" - line 44, col 44)] with root cause
line 44 in employee_add is:
<input th:field="*{name}" type="text" id="name" class="form-control"
EDIT:
I forgot to add the attribute name in quotes:
public String addEmployee(#Valid #ModelAttribute("employee") DTOEmployee dtoEmployee, BindingResult result)
It`s work :)

Related

Unable to fetch UI due to bean validation error getting BindingException

I am getting below error when I am hitting '/signup' API after '/index' API. I have gone through many links. I found mentioned in various resources that the issue is the order of #Valid and BindingResult param needs to be maintained and I see it already in my code still I am unable to find what exactly the problem is. Please help me resolve this issue:
2021-05-31 19:37:40.721 WARN 10224 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 5 errors
Field error in object 'journeyFoodOrder' on field 'contactNoOfGuide': rejected value [null]; codes [NotNull.journeyFoodOrder.contactNoOfGuide,NotNull.contactNoOfGuide,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [journeyFoodOrder.contactNoOfGuide,contactNoOfGuide]; arguments []; default message [contactNoOfGuide]]; default message [Mobile No Of Guide is mandatory]
Field error in object 'journeyFoodOrder' on field 'nameOfCenter': rejected value [null]; codes [NotBlank.journeyFoodOrder.nameOfCenter,NotBlank.nameOfCenter,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [journeyFoodOrder.nameOfCenter,nameOfCenter]; arguments []; default message [nameOfCenter]]; default message [Name Of Center is mandatory]
Field error in object 'journeyFoodOrder' on field 'mealRetrievalTime': rejected value [null]; codes [NotNull.journeyFoodOrder.mealRetrievalTime,NotNull.mealRetrievalTime,NotNull.java.util.Date,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [journeyFoodOrder.mealRetrievalTime,mealRetrievalTime]; arguments []; default message [mealRetrievalTime]]; default message [Meal retrieval time is mandatory]
Field error in object 'journeyFoodOrder' on field 'nameOfGuide': rejected value [null]; codes [NotBlank.journeyFoodOrder.nameOfGuide,NotBlank.nameOfGuide,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [journeyFoodOrder.nameOfGuide,nameOfGuide]; arguments []; default message [nameOfGuide]]; default message [Name Of Guide is mandatory]
Field error in object 'journeyFoodOrder' on field 'dateOfDeparture': rejected value [null]; codes [NotNull.journeyFoodOrder.dateOfDeparture,NotNull.dateOfDeparture,NotNull.java.util.Date,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [journeyFoodOrder.dateOfDeparture,dateOfDeparture]; arguments []; default message [dateOfDeparture]]; default message [Departure date is mandatory]]
Controller Code
#Controller
public class JourneyFoodOrderController {
private final JourneyFoodOrderRepository journeyFoodOrderRepository;
#Autowired
public JourneyFoodOrderController(JourneyFoodOrderRepository journeyFoodOrderRepository) {
// TODO Auto-generated constructor stub
this.journeyFoodOrderRepository = journeyFoodOrderRepository;
}
#GetMapping("/signup")
public String showSignUpForm(#Valid JourneyFoodOrder journeyFoodOrder) {
return "add-journeyFoodOrder";
}
#PostMapping("/addJourneyFoodOrder")
//#Valid AccountForm form, BindingResult result, (binding=false) Account account
public String addJourneyFoodOrder(#Valid JourneyFoodOrder journeyFoodOrder, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-journeyFoodOrder";
}
model.addAttribute("journeyFoodOrder", journeyFoodOrder);
journeyFoodOrderRepository.save(journeyFoodOrder);
return "redirect:/index";
}
#GetMapping("/index")
public String showJourneyFoodOrderList(Model model) {
model.addAttribute("journeyFoodOrders", journeyFoodOrderRepository.findAll());
return "index";
}
}
View Code
<body>
<div class="container">
<div class="row">
<div class="col-md-4 mt-5">
<div id="successMessage"class="alert alert-success" role="alert">
Order saved successfully
</div>
<div id="failureMessage" class="alert alert-danger" role="alert">
Invalid data
</div>
<form action="#" th:action="#{/addJourneyFoodOrder}" th:object="${journeyFoodOrder}"method="post">
<h2 class="mb-5">New Order</h2>
<div class="form-group">
<label for="nameOfCenter">Name of Center</label>
<input type="text" th:field="*{nameOfCenter}" class="form-control" placeholder="Name of Center">
<span th:if="${#fields.hasErrors('nameOfCenter')}" th:errors="*{nameOfCenter}"></span>
</div>
<div class="form-group">
<label for="nameOfGuide">Name of Guide/Teacher</label>
<input type="text" th:field="*{nameOfGuide}" class="form-control" placeholder="Name of Guide">
<span th:if="${#fields.hasErrors('nameOfGuide')}" th:errors="*{nameOfGuide}"></span>
</div>
<div class="form-group">
<label for="headCount">Head count</label>
<input type="number" th:field="*{headCount}" class="form-control" placeholder="Head count">
<span th:if="${#fields.hasErrors('headCount')}" th:errors="*{headCount}"></span>
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
</div>
<div class="form-group">
<label for="dateOfJourney">Mobile No Of Guide</label>
<input type="text" th:field="*{contactNoOfGuide}" class="form-control" placeholder="Mobile No Of Guide">
<span th:if="${#fields.hasErrors('contactNoOfGuide')}" th:errors="*{contactNoOfGuide}"></span>
</div>
<div class="form-group">
<label for="dateOfDeparture">Date of departure</label>
<div class="input-group date" id="datetimepicker2" data-target-input="nearest">
<input type="text" class="form-control datetimepicker-input" data-target="#datetimepicker2" th:field="*{dateOfDeparture}" id="date" placeholder="Choose departure date"/>
<span th:if="${#fields.hasErrors('dateOfDeparture')}" th:errors="*{dateOfDeparture}"></span>
<div class="input-group-append" data-target="#datetimepicker2" data-toggle="datetimepicker">
<div class="input-group-text"><i class="fa fa-calendar-alt"></i></div>
</div>
</div>
</div>
<div class="form-group">
<label for="date">Meal retrieval time:</label>
<div class="input-group date" id="datetimepicker1" data-target-input="nearest">
<input type="text" class="form-control datetimepicker-input" data-target="#datetimepicker1" th:field="*{mealRetrievalTime}" id="date" placeholder="Choose meal retrieval date and time"/>
<span th:if="${#fields.hasErrors('mealRetrievalTime')}" th:errors="*{mealRetrievalTime}"></span>
<div class="input-group-append" data-target="#datetimepicker1" data-toggle="datetimepicker">
<div class="input-group-text"><i class="fa fa-calendar-alt"></i></div>
</div>
</div>
</div>
Model
#Entity
public class JourneyFoodOrder{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#NotBlank(message="Name Of Center is mandatory")
private String nameOfCenter;
#NotBlank(message="Name Of Guide is mandatory")
private String nameOfGuide;
#NotNull(message="Head Count is mandatory")
private int headCount;
#NotNull(message="Mobile No Of Guide is mandatory")
private String contactNoOfGuide;
#NotNull(message="Departure date is mandatory")
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date dateOfDeparture;
#NotNull(message="Meal retrieval time is mandatory")
#DateTimeFormat(pattern = "dd/MM/yyyy h:mm a")
private Date mealRetrievalTime;
#NotNull(message="Thepla Count is mandatory")
private int thepla;
#NotNull(message="Puri Count is mandatory")
private int puri;
#NotNull(message="Roti Count is mandatory")
private int roti;
#NotNull(message="Achar count is mandatory")
private int achar;
#NotNull(message="Jam count is mandatory")
private int jam;
#NotNull(message="Bread count is mandatory")
private int bread;
#NotNull(message="Other items count is mandatory")
private int others;
//..............setters and getters
}
The problem is that you have #Valid annotation on the #GetMapping method:
#GetMapping("/signup")
public String showSignUpForm(#Valid JourneyFoodOrder journeyFoodOrder) {
return "add-journeyFoodOrder";
}
This indicates that JourneyFoodOrder already should be valid when showing the form for the first time, which is never true. Use this in stead:
#GetMapping("/signup")
public String showSignUpForm(JourneyFoodOrder journeyFoodOrder) {
return "add-journeyFoodOrder";
}
I personally find it clearer to do this:
#GetMapping("/signup")
public String showSignUpForm(Model model) {
model.addAttribute("journeyFoodOrder", new JourneyFoodOrder());
return "add-journeyFoodOrder";
}
But both will work fine.
Additional notes:
You need to use #ModelAttribute for your form data object parameter in the #PostMapping method:
public String addJourneyFoodOrder(#Valid #ModelAttribute("journeyFoodOrder") JourneyFoodOrder journeyFoodOrder, BindingResult result, Model model) {
...
}
After fixing the #GetMapping method, you will run into another problem because add-journeyFoodOrder.html has this line that should be removed:
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
You might want to use a dedicated form data object to bind to the HTML form instead of using your entity directly. See Form handling with Thymeleaf for more information on that.

Changed form value does not display on return. Is there a binding problem between Thymeleaf and Spring Boot?

See this thymeleaf snippet in the form:
<form id="onlineRegistrationForm" action="#"
th:action="#{/__${someId}__/registration}" th:object="${onlineRegistrationForm}"
method="post" novalidate class="needs-custom-validation">
...
<div class="form-group">
<label th:for="__${personInstance}__.city" th:text="#{label.city}">city</label>
<input type="text" class="form-control basicAutoComplete"
th:id="__${personInstance}__.city"
aria-describedby="cityHelp" autocomplete="off"
th:placeholder="#{label.city.ph}"
th:field="*{__${personInstance}__.city}"
th:attr="data-noresults-text='__#{search.nf}__'"
th:attrappend="data-url='/__${someId}__/city/like'"
th:errorclass="is-invalid">
<small id="cityHelp" class="form-text text-muted"
th:unless="${#fields.hasErrors('__${personInstance}__.city')}"
th:text="#{label.city.tt}">city</small>
<small id="cityError" class="invalid-feedback"
th:if="${#fields.hasErrors('__${personInstance}__.city')}"
th:errors="*{__${personInstance}__.city}">Errors</small>
</div>
Consider this POST - from a thymeleaf page:
#PostMapping(value = "/{someId}/apply")
public String submitRegistration(#Valid #ModelAttribute(name = "onlineRegistrationForm") OnlineRegistrationForm onlineRegistrationForm,
BindingResult bindingResult,
#PathVariable String someId,
Model model,
RedirectAttributes redirectAttributes)
throws OnlineRegistrationRuntimeException {
...
validateOnlineRegistration(s, onlineRegistrationForm, bindingResult);
...
if (bindingResult.hasErrors()) {
bindingResult.addError(new ObjectError("onlineRegistrationForm", messageSource.getMessage("error.message", new Object[]{""}, LocaleContextHolder.getLocale())));
return "apply";
}
...
Within validateOnlineRegistration, I change some field, say city - because I determined it thru the postal code.
I tracked down this change until into the response message. It's there.
I mean, having the BindingResult directly after the #Valid#Modelattribute,
spring gives me control in the #Controller, so why the heck is the change not displayed on the result page?

Springboot Validation Exception: org.springframework.validation.BeanPropertyBindingResult Exception

I am trying to show validation errors in my form, but I am not able to implement it.
I am trying to pass null values, I get the hibernate validation message but I am not able to see form validation?
Here is my code:
#RequestMapping(value = "/register", method = RequestMethod.POST)
public String saveForm(#Valid Users users,Model model,Errors errors) {
if(errors.hasErrors()) {
return "registerPage";
}
else {
model.addAttribute("message","Registered................");
System.out.println("Save Users TEST------------------------------------>");
userRepository.save(users);
return "register-success";
}
}
Here is the exception:
Field error in object 'users' on field 'salary': rejected value
[null]; codes
[NotNull.users.salary,NotNull.salary,NotNull.java.lang.Integer,NotNull];
arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [users.salary,salary]; arguments []; default message [salary]];
default message [must not be null] Field error in object 'users' on
field 'dept': rejected value []; codes
[Size.users.dept,Size.dept,Size.java.lang.String,Size]; arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [users.dept,dept]; arguments []; default message [dept],10,2];
default message [Length should be in between 2 to 10] Field error in
object 'users' on field 'name': rejected value []; codes
[Size.users.name,Size.name,Size.java.lang.String,Size]; arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [users.name,name]; arguments []; default message [name],30,2];
default message [Length should be in between 2 to 30]]
Here is my User Pojo:
public class Users implements Serializable{
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="id")
private Integer id;
#Column(name="name")
#NotNull
#Size(min=2,max=30,message="Length should be in between 2 to 30")
private String name;
#Column(name="salary")
#NotNull
private Integer salary;
#Column(name="dept")
#NotNull
#Size(min=2,max=10,message="Length should be in between 2 to 10")
private String dept;
....
}
Here is my html form(Using thymeleaf):
<h1 th:text="${message}" align="center"></h1>
<div class="container">
<h2>Registration form</h2>
<form class="form-horizontal" th:object="${registerCommand}" th:action="#{/rest/users/register}" method="post">
<div class="form-group">
<label for="name">Username:</label>
<input type="text"
class="form-control" id="name" placeholder="Enter Name"
name="name" th:field="*{name}"> <br />
<p th:if="${#fields.hasErrors('name')}" th:errors="*{name}" th:field="*{name}"
class="alert alert-danger"></p>
</div>
<div class="form-group">
<label for="dept">Department:</label>
<input type="text"
class="form-control" id="dept" placeholder="Enter Department"
name="dept" th:field="*{dept}"> <br />
<p th:if="${#fields.hasErrors('dept')}" th:errors="*{dept}" th:field="*{dept}"
class="alert alert-danger"></p>
</div>
<div class="form-group">
<label for="salary">Salary:</label> <input type="text"
class="form-control" id="salary" placeholder="Enter salary"
name="salary" th:field="*{salary}"> <br />
<p th:if="${#fields.hasErrors('salary')}" th:errors="*{salary}" th:field="*{salary}"
class="alert alert-danger"></p>
</div>
<button type="submit" class="btn btn-sucess">Submit</button>
</form>
</div>
Found my reason , i was not passing the correct parameters in my saveForm Controller-
#RequestMapping(value = "/register", method = RequestMethod.POST)
public String saveForm(#ModelAttribute("registerCommand") #Valid Users users, BindingResult bindingResult, Model model){
if(bindingResult.hasErrors()) {
return "registerPage";
}
else {
userRepository.save(users);
return "register-success";
}
}
Note-If you are using BindingResult,it should be exactly after the bean.
It is only BindingResult where the order matters. It must follow the bean that is being validated so that Spring knows where to put any validation errors.
Thanks to David Lavender's answer
https://stackoverflow.com/a/29075342/6547517
Field 'salary' on object User may be null
Check what data you are passing in user object while saving it, there might be salary value is going as null. As you have used #valid on Users , it will not take null or empty value in the input request data

how to get form values to controller in spring mvc

I am trying to get form values from jsp to controller in spring mvc, but i am not able to get form data.
This is my DTO (bean)
public class LoginDTO implements Serializable {
private Long id;
private String username;
private String password;
// setter and getter methods
}
and my Jsp
<form class="form-signin" action="test" method="get" modelAttribute="userFormData">
<input type="text" class="form-control"
placeholder="Email" required autofocus>
<input type="password" class="form-control"
placeholder="Password" required>
<input class="btn btn-md btn-success btn-block"
type="submit" value="Signin">
</form>
and my controller
#RequestMapping(value = "/test", method = RequestMethod.GET)
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result) {
System.out.println("Controller...");
System.out.println("=====> " + formData.getUsername());
System.out.println("=====> " + formData.getPassword());
}
Add names to the controls on your JSP pages.
<input type="text" name="username" ...>
<input type="password" name="password" ...>
To let spring understand which form control value should go to which property of the LoginDTO
we can also use the springframework has given us a form tags.so that we can also use that but in that case you have to define your the input path same as the member varibale given in your class.
like this
<form:form method="post" modelAttribute="userFormData">
<form:input path="username" />
<form:input path="password" />
Then in the controller you can write like this as you have written
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result)
In case you want to get the result on other jsp page as well as on console then do:
public String checkLogin(#ModelAttribute("userFormData") LoginDTO formData, BindingResult
result , Model model){
System.out.println("=====> " + formData.getUsername()); //this outputs username on console
System.out.println("=====> " + formData.getPassword()); //this outputs password on console
model.addAttribute("LoginDTO ", LoginDTO );
return "success"; //this is the return page where the username and password will be rendered as view
}

Spring MVC validation errors are not displayed in Freemarker template

I'm trying to display validation errors in a 'user registration' page built with freemarker template if a controller returns binding errors.
My controller's code is as follows:
#Controller
#RequestMapping("/")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(Model model) {
model.addAttribute("userForm", new User());
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute("useraccount") User userForm, BindingResult bindingResult, Model model) {
userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) {
return "registration";
}
userService.save(userForm);
securityService.autologin(userForm.getUsername(), userForm.getPasswordConfirm());
return "redirect:/explore";
}
while this is the registration.ftl freemarker template I am trying to build :
<div>
<fieldset>
<h1>Create your Account</h1>
<form id="regForm" class="idealform" action="registration" method="post" name='useraccount'>
Username: <input type="text" name="username" /> <errors path="username" cssClass="error"/><br/>
Password: <input type="text" name="password" /><errors path="password" cssClass="error"/><br/>
<label class="main-label" style="width: 91px;"> </label>
<input type="submit" value="submit">
</form>
</fieldset>
I tried also the solution recommended here:
Displaying Spring MVC validation errors in Freemarker templates
and the registration.ftl becomes:
<#assign form=JspTaglibs["http://www.springframework.org/tags/form"] />
<#macro formErrors>
<#assign formErrors><#form.errors path="*" /></#assign>
<#if formErrors?has_content>
<div id="errors">
<#spring.message "admin.error.globalMessage" />
</div>
</#if>
</#macro>
<div>
<fieldset>
<h1>Create your Account</h1>
<#form.form id="regForm" class="idealform" action="registration" method="post" name='useraccount'>
Username: <input type="text" name="username" path="username" /> <br/>
Password: <input type="text" name="password" path="password" /><br/>
<#formErrors />
<label class="main-label" style="width: 91px;"> </label>
<input type="submit" value="submit">
</#form.form>
</fieldset>
</div>
but still the validation messages are not displayed.
Could you share your thoughts with me on this issue?
Thank you very much.
I rewrote your controller code to something like this:
#Controller
#RequestMapping("/")
public class UserController {
#Autowired
private UserService userService;
#Autowired
private SecurityService securityService;
#Autowired
private UserValidator userValidator;
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public String registration(#ModelAttribute(name = "userForm") User user) {
return "registration";
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String registration(#ModelAttribute(name = "userForm") User user, BindingResult result) {
userValidator.validate(user, result);
if (result.hasErrors()) {
return "registration";
}
userService.save(user);
securityService.autologin(user.getUsername(), user.getPasswordConfirm());
return "redirect:/explore";
}
}
1) There is no need to use model.addAttribute("modelName", model) if you use a constructor without arguments, instead you can use a #ModelAttribute annotation specifying the name attribute (by default the name goes from the class name). You only have to be sure that this model is in a consistent state. Also you need to pass the name exactly the same as you use in your view (freemarker template).
Now "registration.ftl"
...
<#import "/spring.ftl" as spring/>
...
<fieldset>
<h1>Create your Account</h1>
<form id="regForm" class="idealform" action="<#spring.url '/registration'/>" method="post">
<#spring.bind 'userForm.username'/>
Username: <input type="text" name="${spring.status.expression}" value="${spring.status.value?html}"/>
<#list spring.status.errorMessages as error>
<span class="error">${error}</span>
<br>
</#list>
<#spring.bind 'userForm.password'/>
Password: <input type="password" name="${spring.status.expression}" value="${spring.status.value?html}"/>
<#list spring.status.errorMessages as error>
<span class="error">${error}</span>
<br>
</#list>
<label class="main-label" style="width: 91px;"> </label>
<input type="submit" value="submit">
</form>
</fieldset>
...
1)You need <#import "/spring.ftl" as spring/> in order to add spring's user-defined directives that are pretty useful.
2)Use <#spring.bind 'userForm.username'> directive to bind following input to your model. Here "userForm" is your model and "username" is a field that you want to bind. This directive also declares new variable "spring.status" that contains an "expression" variable - for a path, a "value" - to populate the form in case it's returned with errors, and "errorMessages" from BindingResult.
3)If you use a message source to support different languages you should change <span class="error">${error}</span> to something like <#spring.message '${error}'/> otherwise you'll get just message codes.
Hope it helps.

Resources