Spring MVC form handling example
In Spring MVC, form controller is used to handle the form submission task (binding values to/from Spring’s form tags). Often times, you may just need to extend the SimpleFormController to inherit the form handling ability.
1. Binding Values
In SimpleFormController, you need to tell Spring about how form controller will binds the value to/from the HTML form’s components. See code snippet :
public class YourController extends SimpleFormController{ //... public CustomerController(){ setCommandClass(Customer.class); setCommandName("customerForm"); }
- setCommandClass(Customer.class) – Form’s values will store into this Customer object.
- setCommandName(“customerForm”) – If HTML form action value with named “customerForm” is submitted, Spring will forward request to this form controller.
2. Form submission
When HTML form is submitted, form controller’s onSubmit() method will be executed, to handle the submitted form’s value and return a ModelAndView if success. So, onSubmit() method is the ideal place to perform form submission business logic.
public class YourController extends SimpleFormController{ //... @Override protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { Customer customer = (Customer)command; System.out.println(customer); return new ModelAndView("CustomerSuccess","customer",customer); }
3. Initialization
In some cases, you may need to initialize the form component values before render the page, like default value for HTML form component. To do this, just override the formBackingObject() method.
public class YourController extends SimpleFormController{ //... @Override protected Object formBackingObject(HttpServletRequest request) throws Exception { Customer cust = new Customer(); cust.setFavFramework(new String []{"Spring MVC"}); return cust; }
This technique is useful to set a default selected value for HTML components, like checkbox , radio button or select options.
4. Data Referencing
Provide a list of data for HTML components, like checkbox , radio button or select options. To do this, just override the referenceData() method.
public class YourController extends SimpleFormController{ //... @Override protected Map referenceData(HttpServletRequest request) throws Exception { Map referenceData = new HashMap(); List<String> webFrameworkList = new ArrayList<String>(); webFrameworkList.add("Spring MVC"); webFrameworkList.add("Struts 1"); webFrameworkList.add("Struts 2"); referenceData.put("webFrameworkList", webFrameworkList); return referenceData; }
5. SimpleFormController bean
Finally, declares the SimpleFormController bean and override the “formView” and “successView” property value.
- formView – Indicate the form page that will shows to the user. If validation failed, the controller will return this page to the user as well.
- successView – If the form is submitted successful, return this page to the user.
With below InternalResourceViewResolver declared :
<bean class="com.mkyong.customer.controller.CustomerController"> <property name="formView" value="CustomerForm" /> <property name="successView" value="CustomerSuccess" /> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean>
- “formView” will redirect to “/WEB-INF/pages/CustomerForm.jsp”.
- “successView” will redirect to “/WEB-INF/pages/CustomerSuccess.jsp”.
Spring MVC form handling example
In this example, it will use the Spring’s form tags to render the textbox, password, textarea, checkbox, radio button, select option and hidden value field. And all the submitted form values will be handle by the SimpleFormController. Additionally, attach a simple validator to do the empty checking on the HTML form components, if the validation failed, use the form’s error tag to output the error message associated with the field. By studying this example, you should have a very good understanding of the form handling in Spring MVC.
1. Model
A Customer model object for the demonstration.
File : Customer.java
package com.mkyong.customer.model; public class Customer{ //textbox String userName; //textarea String address; //password String password; String confirmPassword; //checkbox boolean receiveNewsletter; String [] favFramework; //radio button String favNumber; String sex; //dropdown box String country; String javaSkills; //hidden value String secretValue; //getter and setter methods }
2. Form Controller
A SimpleFormController class to handle the form submission.
File : CustomerController.java
package com.mkyong.customer.controller; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.validation.BindException; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.SimpleFormController; import com.mkyong.customer.model.Customer; public class CustomerController extends SimpleFormController{ public CustomerController(){ setCommandClass(Customer.class); setCommandName("customerForm"); } @Override protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { Customer customer = (Customer)command; System.out.println(customer); return new ModelAndView("CustomerSuccess","customer",customer); } @Override protected Object formBackingObject(HttpServletRequest request) throws Exception { Customer cust = new Customer(); //Make "Spring MVC" as default checked value cust.setFavFramework(new String []{"Spring MVC"}); //Make "Make" as default radio button selected value cust.setSex("M"); //make "Hibernate" as the default java skills selection cust.setJavaSkills("Hibernate"); //initilize a hidden value cust.setSecretValue("I'm hidden value"); return cust; } @Override protected Map referenceData(HttpServletRequest request) throws Exception { Map referenceData = new HashMap(); //Data referencing for web framework checkboxes List<String> webFrameworkList = new ArrayList<String>(); webFrameworkList.add("Spring MVC"); webFrameworkList.add("Struts 1"); webFrameworkList.add("Struts 2"); webFrameworkList.add("JSF"); webFrameworkList.add("Apache Wicket"); referenceData.put("webFrameworkList", webFrameworkList); //Data referencing for number radiobuttons List<String> numberList = new ArrayList<String>(); numberList.add("Number 1"); numberList.add("Number 2"); numberList.add("Number 3"); numberList.add("Number 4"); numberList.add("Number 5"); referenceData.put("numberList", numberList); //Data referencing for country dropdown box Map<String,String> country = new LinkedHashMap<String,String>(); country.put("US", "United Stated"); country.put("CHINA", "China"); country.put("SG", "Singapore"); country.put("MY", "Malaysia"); referenceData.put("countryList", country); //Data referencing for java skills list box Map<String,String> javaSkill = new LinkedHashMap<String,String>(); javaSkill.put("Hibernate", "Hibernate"); javaSkill.put("Spring", "Spring"); javaSkill.put("Apache Wicket", "Apache Wicket"); javaSkill.put("Struts", "Struts"); referenceData.put("javaSkillsList", javaSkill); return referenceData; } }
3. Form Validator
A form validator class to do the empty checking on the HTML components. If validation failed, get the error message from resource bundle, and associate it with the corresponds error field.
In form views, you can use the <form:errors /> to renders and format the error message that is associated with the field.
package com.mkyong.customer.validator; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import com.mkyong.customer.model.Customer; public class CustomerValidator implements Validator{ @Override public boolean supports(Class clazz) { //just validate the Customer instances return Customer.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName", "required.userName", "Field name is required."); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "address", "required.address", "Field name is required."); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "required.password", "Field name is required."); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "confirmPassword", "required.confirmPassword", "Field name is required."); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "sex", "required.sex", "Field name is required."); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "favNumber", "required.favNumber", "Field name is required."); ValidationUtils.rejectIfEmptyOrWhitespace( errors, "javaSkills", "required.javaSkills","Field name is required."); Customer cust = (Customer)target; if(!(cust.getPassword().equals(cust.getConfirmPassword()))){ errors.rejectValue("password", "notmatch.password"); } if(cust.getFavFramework().length==0){ errors.rejectValue("favFramework", "required.favFrameworks"); } if("NONE".equals(cust.getCountry())){ errors.rejectValue("country", "required.country"); } } }
A properties file to store all the error messages.
File : Customer.properties
required.userName = Username is required! required.address = Address is required! required.password = Password is required! required.confirmPassword = Confirm password is required! required.favFrameworks = Please select at least a web frameworks! required.sex = Please select a sex! required.favNumber = Please select a number! notmatch.password = Password and Conform password is not match!
4. View
This is the “formView“, render the HTML components with Spring’s form tags, display and highlight the error message if any.
File : CustomerForm.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html> <head> <style> .error { color: #ff0000; } .errorblock { color: #000; background-color: #ffEEEE; border: 3px solid #ff0000; padding: 8px; margin: 16px; } </style> </head> <body> <h2>Spring's form tags example</h2> <form:form method="POST" commandName="customerForm"> <form:errors path="*" cssClass="errorblock" element="div" /> <table> <tr> <td>UserName :</td> <td><form:input path="userName" /> </td> <td><form:errors path="userName" cssClass="error" /> </td> </tr> <tr> <td>Address :</td> <td><form:textarea path="address" /> </td> <td><form:errors path="address" cssClass="error" /> </td> </tr> <tr> <td>Password :</td> <td><form:password path="password" /> </td> <td><form:errors path="password" cssClass="error" /> </td> </tr> <tr> <td>Confirm Password :</td> <td><form:password path="confirmPassword" /> </td> <td><form:errors path="confirmPassword" cssClass="error" /> </td> </tr> <tr> <td>Subscribe to newsletter? :</td> <td><form:checkbox path="receiveNewsletter" /> </td> <td><form:errors path="receiveNewsletter" cssClass="error" /> </td> </tr> <tr> <td>Favourite Web Frameworks :</td> <td><form:checkboxes items="${webFrameworkList}" path="favFramework" /></td> <td><form:errors path="favFramework" cssClass="error" /> </td> </tr> <tr> <td>Sex :</td> <td><form:radiobutton path="sex" value="M" />Male <form:radiobutton path="sex" value="F" />Female</td> <td><form:errors path="sex" cssClass="error" /> </td> </tr> <tr> <td>Choose a number :</td> <td><form:radiobuttons path="favNumber" items="${numberList}" /> </td> <td><form:errors path="favNumber" cssClass="error" /> </td> </tr> <tr> <td>Country :</td> <td><form:select path="country"> <form:option value="NONE" label="--- Select ---" /> <form:options items="${countryList}" /> </form:select></td> <td><form:errors path="country" cssClass="error" /> </td> </tr> <tr> <td>Java Skills :</td> <td><form:select path="javaSkills" items="${javaSkillsList}" multiple="true" /></td> <td><form:errors path="javaSkills" cssClass="error" /> </td> </tr> <form:hidden path="secretValue" /> <tr> <td colspan="3"><input type="submit" /></td> </tr> </table> </form:form> </body> </html>
This is the “successView“, renders all the submitted values.
Fie : CustomerSuccess.jsp
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <body> <h2>Spring's form tags example</h2> <table> <tr> <td>UserName :</td> <td>${customer.userName}</td> </tr> <tr> <td>Address :</td> <td>${customer.address}</td> </tr> <tr> <td>Password :</td> <td>${customer.password}</td> </tr> <tr> <td>Confirm Password :</td> <td>${customer.confirmPassword}</td> </tr> <tr> <td>Receive Newsletter :</td> <td>${customer.receiveNewsletter}</td> </tr> <tr> <td>Favourite Web Frameworks :</td> <td><c:forEach items="${customer.favFramework}" var="current"> [<c:out value="${current}" />] </c:forEach> </td> </tr> <tr> <td>Sex :</td> <td>${customer.sex}</td> </tr> <tr> <td>Favourite Number :</td> <td>${customer.favNumber}</td> </tr> <td>Java Skills :</td> <td>${customer.javaSkills}</td> </tr> <tr> <td>Hidden Value :</td> <td>${customer.secretValue}</td> </tr> <tr> <td>Hidden Value :</td> <td>${customer.secretValue}</td> </tr> </table> </body> </html>
5. Spring Bean Configuration
Finally, link the properties file, validator and form controller together.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" /> <bean class="com.mkyong.customer.controller.CustomerController"> <property name="formView" value="CustomerForm" /> <property name="successView" value="CustomerSuccess" /> <!-- Map a validator --> <property name="validator"> <bean class="com.mkyong.customer.validator.CustomerValidator" /> </property> </bean> <!-- Register the Customer.properties --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="com/mkyong/customer/properties/Customer" /> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans>
6. Demo
Access the page – http://localhost:8080/SpringMVC/customer.htm

If the user failed the validation, display and highlight the error message.

If the form is submitted successfully, just display all the submitted values.

Download Source Code
References
- http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html
- http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/mvc/SimpleFormController.html
- http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/validation/Validator.html
- http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/validation/ValidationUtils.html
- http://static.springsource.org/spring/docs/2.5.x/reference/validation.html

Hi,
I really benefitted from this tutorial. Just one question, when you access the form with customer.htm in your url how does Spring know to link this url with your JSP?
Heya i’m for the primary time here. I came across this board and I in finding It truly helpful & it helped me out much. I am hoping to present something back and aid others such as you aided me.
Hello would you mind stating which blog platform you’re working with? I’m
planning to start my own blog in the near future but I’m having a difficult time choosing between BlogEngine/Wordpress/B2evolution and Drupal. The reason I ask is because your design and style seems different then most blogs and I’m looking for
something unique. P.S My apologies for getting off-topic but I had to
ask!
Hello!
I met the following problem when deploying to tomcat
java.lang.NoSuchMethodError: org.springframework.core.GenericTypeResolver.resolveTypeArguments(Ljava/lang/Class;Ljava/lang/Class;)[Ljava/lang/Class;
I resolved it by removing this dependency
Instead I put this:
org.springframework spring-corehi Mkyong,
Thanks for the tutorial.
can you please explain me the difference between the formbackingobject() vs referencedate()
I have some html controls in my page, they have the same ID, how can I generate something similar to to each control?
<input type="text" id="mycontrol” />
Any idea?
thanks!
thanks for nice explanation.
Nice explanation sir
Sir i am new one for spring. Some xml files are not supported in Google App Engine so what i do.
the class SimpleFormController was deprecated in the new Spring version, kindly did you know which class that we can use in the place of the deprecated one.
Is there Any example for MultiAction COntroller Form Validation
Thank you very much yong. It’s really nice.
Thank you for your step by step example. For the edit, how to set up bean configuration? I found all the examples are for the add and I have not found for edit yet. Could you guide me? I tried with as below but not working and it is showing error.
Hi,
Why do you use package access for properties in Customer.java instead of private ones?
Regards
Good example , unfortunately its not working for me, no meter what i do , the customer form jsp just not loaded :”Oops! This link appears to be broken.”
Use this link
http://localhost:8080/SpringMVC/customer.htm
Example is good! It was usefully =)
I`m not sure, but if you didn`t added this string in pom.xml
You will get: SpringMVCForm/src/main/java/com/mkyong/customer/controller/CustomerController.java:[24,2] error: annotations are not supported in -source 1.3
and
/SpringMVCForm/src/main/java/com/mkyong/customer/controller/CustomerController.java:[61,6] error: generics are not supported in -source 1.3
Somebody can explain this?
Maven uses JDK 1.3 to compile, which is not support annotation yet. So, your configuration is right, thanks for your input.
A thorough A to Z steps explaining a SimpleFormController
Real BIG help
Thanks Buddy
Thanks for nice explanation….
Hi Mkyong,
Im newbie for Springs.,
I implemented same form example, but formBackingObject method gets called twice.
Dnt know y.
Please can u guide me ?
Thanks in advance.
Hi,
this example need to modify 2 files to make it work.
- file at SpringMVCForm\.classpath
- file at SpringMVCForm\.settings\org.eclipse.wst.common.project.facet.core.xml
add more:
what a clear explanation!!!!!!
i download and run on my maven eclipse but i get a http error 404. The webpage cannot be found. i emphasize its a helpful article.
Good one. Thanks for this tutorial.
Please keep writing more
Once again thanks a lot for the nice and clear tutorial!
Dear friend,
I really impressed by this website.
Good work buddy.
Mkyong -
Thank you for such a wonderful, lightweight and easy to follow set of tutorials. I am new to Spring and I find your tutorials much easier to work with the the Spring reference manual.
I do have one question – is there an easy way of populating the ‘referencedata’ map dynamically via a properties file or XML? I’m just thinking it would be good to be able to change these values without re-building and re-deploying the app. I appreciate I could write some java code to do it via a Properties object but surely something already exists ‘out of the box’?
Thanks again,
Kai
One of the best examples i have ever seen on Spring MVC. Great Work. Keep it up!
Hi,
I downloaded this code and when i try to access customer.htm, it gives me
org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/SpringMkyong/customer.htm] in DispatcherServlet with name ‘dispatcher’
Why i am getting like this? i googled it but if of no use.
Did you build with Maven to get all project dependencies?
hi mkyong,
I would like to ask how to retain the list value in referenceData() in the submission pass the validate checking and throw error in onSubmit method?
if there is error in onSubmit method i try to forward to back the same and show errors but the reference data is missing e.g. list options in selection box becomes empty.
Thanks dude you have given best description for spring
Keep up the good work
hi mkyong,
my english is not good, thank you !!!
I tried this example successfully. I later tied a step ahead where I submit in page1(jsp page) then instead of displaying in page2(jsp), I have comeup with a form in pag2 where user inputs data. Page1 has a command class(mentioned in jsp and bean definition(commandclass and command name)), page2 has a different command class, with a different commandclassName. As I click submit on page 1, instead of displaying page2, it is giving the error
“Neither BindingResult nor plain target object for bean name ‘customerForm’ available as request attribute”
Cutting and pasting that does not work in MVC3. To get the extension to work, I had to create a class file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace incMvcSite.Classes {
public static class HtmlPrefixScopeExtensions {
public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix) {
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}
private class HtmlFieldPrefixScope : IDisposable {
private readonly TemplateInfo templateInfo;
private readonly string previousHtmlFieldPrefix;
public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix) {
this.templateInfo = templateInfo;
previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}
public void Dispose() {
templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
}
}
}
}
In the Razor (.cshtml) file, I added the following:
@using incMvcSite.Classes
@using(Html.BeginHtmlFieldPrefixScope(“Permission”)) {
Permission
// The Html.EditorFor’s would go here…
}
Notice the using to bring me extension class into scope. That allows the second using line to work.
Now the problem is that when posting back, the object is not updated. In my controller, I used a second parameter to specify my prefix:
TryUpdateModel(modelUser.Permission, “Permission”);
This added the prefix to all field in the HTML, and the TryUpdateModel loaded the object with prefixed control names. Now you can properly namespace your controls for embedded edit lists, and for partial views of models with the same property names.
Shawn Zernik
Internetwork Consulting
Thanks for your invaluable comment, your code is .NET, right? Not familiar with .NET MVC, is this similar with Spring MVC?
What Java compiler do you use? Got error as below:
Description Resource Path Location Type
Java compiler level does not match the version of the installed Java project facet. SpringMVCForm Unknown Faceted Project Problem (Java Version Mismatch)
I should be using jdk1.6 to compile this example.
I tried JDK 1.5 and 1.6; both got the same error. BTW, I used MyEClipse as IDE. Does that make difference?
Thanks.
Then get a Eclipse and test :) . This example is tested under Eclipse 3.6 + Maven 2.x + JDK1.6
This was a great example. Probably the best I’ve seen so far!
Thanks so much for taking the time to do this. one question though. I’ve not seen any examples where there are form inputs and data from other pages all on the same page.
for example. If I entered a date on one page. Continue on in the process, and on a later page, where I’m asking for more data (from form inputs) display the dates from the previous step.
Or using your example here, If you had the username entered on a separate page, and then on the customer page displayed that name and had the inputs for the rest of the data needed.
Thanks for any help you can give.
Thank you for a wonderful article.. very much helpful for noobs like me…
welcome, i’m noobs also, we all learn through the process :)
how to provide the default value in the text field using form:input tag in spring
how to provide the default value in the text field using tag
Hi,
For a late learner your identical examples of using annotations and doing the same without have been a lifesaver.
I hope you keep writing!
Thanks for your kind comment, and good to know it did help someone :)
Where have you marked the welcome page to be customer.htm?Nothing is mentioned about customer.htm in your application.
http://localhost:8080/SpringMVC/customer.htm
If URL “customer” pattern is requested, it will send to “CustomerController” controller to handle the request.
You may interest at this article
http://www.mkyong.com/spring-mvc/spring-mvc-hello-world-example/
But you havent declared a bean name “/customer.htm” and map it to CustomerController class in the above example. Then how is it possible if an URL with “/customer.htm” pattern is requested, it will send to CustomerController controller to handle the request?
Please check the Spring MVC hello world example in this link http://www.mkyong.com/spring-mvc/spring-mvc-hello-world-example/
In web.xml, you can map all the “.htm” file extension to Spring. So, if “customer.htm” is requested, Spring will assign to CustomerController.java automatically.
If the request from /customer.htm goes to the controller class then why CustomerForm.jsp file is used here in this example ? confused. A html page cannot use spring form library. Please clarify.
Nice Blog Post, but why didn’t you use a single annotation?
They make life so much easier and you don’t have to use subclassing for the controllers etc. and you can unittest it much better.
Hi, thanks for your suggestion, will create a form handling example in annotation version soon :)
Any progress?