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");
	}
  1. setCommandClass(Customer.class) – Form’s values will store into this Customer object.
  2. 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;
	}
Note
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.

  1. 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.
  2. 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>
  1. “formView” will redirect to “/WEB-INF/pages/CustomerForm.jsp”.
  2. “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.

Note
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

SpringMVC-Form-Handle-Example-1

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

SpringMVC-Form-Handle-Example-2

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

SpringMVC-Form-Handle-Example-3

Download Source Code

References

  1. http://static.springsource.org/spring/docs/2.5.x/reference/mvc.html
  2. http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/servlet/mvc/SimpleFormController.html
  3. http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/validation/Validator.html
  4. http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/validation/ValidationUtils.html
  5. http://static.springsource.org/spring/docs/2.5.x/reference/validation.html
Tags :
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider making a donation to the charity, thanks.

Related Posts

Popular Posts