Spring MVC Form Handling Example

In this post we will discuss about Spring forms and data binding to a controller.Spring MVC has provided tag library to create Form. The Form will be associated with a bean. When we submit the form, the associated bean will automatically be populated. The bean will be used for further processing.

As part of this article we will discuss on below important concepts of Spring MVC.

  • ModelAndView
  • @ModelAttribute
  • ModelMap
  • Command Object

In this post we will discuss about Spring forms and data binding to a controller.Spring MVC has provided tag library to create Form. The Form will be associated with a bean. When we submit the form, the associated bean will automatically be populated. The bean will be used for further processing.

As part of this article we will discuss on below important concepts of Spring MVC.

  • ModelAndView
  • @ModelAttribute
  • ModelMap
  • Command Object


Project Structure:

The following screenshot shows final structure of the project:


Spring MVC Form


Requirement Detail

We are going to create a registration form form providing an interface to the students for participating to an event.


We have to follow bellow steps to successfully implement our requirement :

  • First of all we have to a domain object or pojo class (User.java) for holding form values provided by the user.
  • Then, we will configure our spring configuration file (app-config.xml) to adopt annotation driven configuration for spring mvc.
  • After that we will implement our controller class (RegistrationController.java) that will handle two types of request. One for showing the form to the user and another for processing the input data of form.
  • Then, we will create the form jsp page (registration.jsp) using spring mvc ui taglibs and a registration success page (success.jsp) for the form to confirm the input data in form.
  • After that we will see how to change the error message for data conversion in message resource file (messages.properties).

Follow the steps mentioned below to develop this application.


Step 1: Create Dynamic Web Project in Maven

To create dynamic web project with maven, navigate to the folder where you want to create the project and execute following command in Command Prompt.

mvn archetype:generate -DgroupId=com.jwt.spring -DartifactId=SpringMVCForm -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false

Above command will create a dynamic web project with name SpringMVCForm.



Step 2: Convert Maven Project to support Eclipse

To make maven project support eclipse IDE navigate to project folder and type followingcommand in terminal window.

mvn eclipse:eclipse -Dwtpversion=2.0

Now Import the project into eclipse.


Step 3: Add project dependency in pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.jwt.spring</groupId>
	<artifactId>SpringMVCForm</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>SpringMVCForm Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<properties>
		<spring.version>4.0.1.RELEASE</spring.version>
		<junit.version>4.8.2</junit.version>
	</properties>
	<dependencies>
		<!-- Spring Dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- Spring Test -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>

		<!-- Mockito -->
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>1.8.4</version>
		</dependency>

		<!-- Junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<!-- Bellow will be used while running Junit -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
	<build>
		<finalName>SpringMVCForm</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


Step 4 : Create java directory :

Create a folder named 'java' under main."/src/main" and add this folder to the class path of the project.


Step 5: Creating Model Class (form-backing object)

For this example application, User.java class is used as model. It will hold the data which view will use to render and post back to controller.Create User.java in com.jwt.bean package and add below line of code in this file.

User.java

package com.jwt.bean;

public class User {

	private String name;
	private String email;
	private int age;
	private String sex = null;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", Email=" + email + ", age=" + age
				+ ", sex=" + sex + "]";
	}
}

We have created the above POJO for capturing the form data. We will use this as command object for the form. Command object is an ordinary object which holds the form data.


Step 6: Creating Deployment Descriptor (web.xml)

We need to configure spring MVC framework in our application, that can be done by configuring Spring framework DispatcherServlet as front controller in web.xml as below.We specify there that we want to use class org.springframework.web.servlet.DispatcherServlet as our main servlet and we map it to handle any requests arriving to our application.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">

	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

</web-app>

Step 7: Creating Spring Configuration file (spring-servlet.xml)

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- Scans the classpath of this application for @Components to deploy as 
		beans -->
	<context:component-scan base-package="com.jwt" />

	<!-- Configures the @Controller programming model -->
	<mvc:annotation-driven />

	<!-- Specifying the Resource location to load JS, CSS, Images etc -->
	<mvc:resources mapping="/resources/**" location="/resources/" />

	<!-- View Resolver -->
	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/pages/" />
		<property name="suffix" value=".jsp" />
	</bean>
	<bean id="messageSource"
		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="basename" value="classpath:messages" />
	</bean>


</beans>

In the above spring configuration file we specified two important tags <context:component-scan> to inform Spring that we want to use annotations for our beans located under given base package 'com.jwt', and <mvc:annotation-driven> to inform Spring that we want to use annotations for our web controllers . Without annotations we would have to add every bean and web controller definition to this file which will greatly increase its size.

We also inform Spring that we want to hold our static resources like images, CSS files and scripts under /resources/ directory of our application. By adding mapping attribute we tell Spring that whenever any HTTP request arrives for URL starting with /resources/, we want to return one of our resources. Defining static resources improves performance because Spring will serve the resources directly without any checking or processing.



Step 8: Creating Controller Class

In our application we have to tell Spring which URLs we can handle and how. We can do so by creating a web controller class.

Our controller class will handle two requests, one for displaying the registration form and another to handle the submitted form data. Here we have two functions with same request mapping url but the request type will be different. For showing the registration form the request type will be GET and for processing form data submission the request type will be POST. See the bellow code to understand how to specify request type and process form :

RegistrationController.java

package com.jwt.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.jwt.bean.User;

@Controller
@RequestMapping(value = "/registration")
public class RegistrationController {

	@RequestMapping(method = RequestMethod.GET)
	public String showForm(ModelMap model) {
		User user = new User();
		model.addAttribute("USER", user);
		return "registration";
	}

	@RequestMapping(method = RequestMethod.POST)
	public String processForm(@ModelAttribute(value = "USER") User user,
			BindingResult result) {
		if (result.hasErrors()) {
			return "registration";
		} else {
			System.out.println("User values is : " + user);
			return "success";
		}
	}
}

Important Points

In the above controller class Annotations @Controller and @RequestMapping at class level inform Spring that this class is a web controller and will serve requests for /registration relative URL.

There is no need to add this class to any configuration file because Spring will automatically scan all classes within base package specified in XML configuration file and register them.

As, you can see the class is annotated with @RequestMapping(value=”/registration”), It means all the methods in this class will handle the request for the url '/registration'. showForm() method will handle the GET request type and will show the registration form. showForm() method also adds a new instance to the model map so that the new instance can be associated with the shown form. processForm() method processes the form data.

  • @ModelAttribute(value="USER") : ModelAttribute annotation will tell spring mvc framework that the 'USER' model instance should be assigned as an instance of User class and should be pass to the method processForm().
  • BindingResult result : Spring will find our if any error occur during the creation of User class instance from model instance 'USER' and if any error came its description will be pass the method as BindingResult instance.If there is any error present than it will show again the registration form and if there is no error then success page will be shown to the user.

Step 9: Creating form views

First of all create one welcome file index.jsp. In this jsp file we are simply redirecting the reuest to 'registration' url.

index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<jsp:forward page="/registration"></jsp:forward>

In the above jsp file whats happening is when request is coming to this application immediately it is forwarded to 'registration' url and request is taken care by 'RegistrationController' class 'showForm() method because request mapping is mentioned as @RequestMapping(value = "/registration").

This application uses two views i.e. one for displaying registration form and another for displaying success page.

Create a folder jsp inside WEB-INF directory and then create a jsp file registration.jsp inside this folder.

registration.jsp

registration.jsp will show, how spring mvc form tag will be used to show the form elements in jsp and how errors are shown to the user if any occur. Following is the code of registration.jsp

<%@ page session="true"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Registartion Page</title>
</head>
<body>
	<h1>Registration Form</h1>
	<p></p>
	<form:form method="post" commandName="USER">
		<table>
			<tr>
				<td colspan="2"><form:errors path="*" cssStyle="color : red;" />
				</td>
			</tr>
			<tr>
				<td>Name :</td>
				<td><form:input path="name" /></td>
			</tr>
			<tr>
				<td>Email :</td>
				<td><form:input path="email" /></td>
			</tr>
			<tr>
				<td>Age :</td>
				<td><form:input path="age" /></td>
			</tr>
			<tr>
				<td>Sex :</td>
				<td><form:select path="sex">
						<form:option value="Male" />
						<form:option value="Female" />
					</form:select></td>
			</tr>
			<tr>
				<td colspan="2"><input type="submit" value="Save Changes" /></td>
			</tr>
		</table>
	</form:form>
</body>
</html>

Important Points:

  • On the above login form, we used tag. which is completely given by the spring framework. to get the <form:form> tag into our jsp. we need to add the tag library like below. <%@taglib uri=”http://www.springframework.org/tags/form” prefix=”form”%>
  • The Spring <form:form> tag declares two attributes. The method="post" attribute used to indicate a form performs an HTTP POST request upon submission. And the modelAttribute="USER" attribute used to indicate the form data is bound to a model named USER.
  • <form:form  method="post" commandName="USER">
    
  • Form’s various <form:input> tags make use of the attribute path to indicate the form’s fields to which they are bind.See the form code. We have used path.For example <form:input path="name" />. It just sets name in the command object.
  • <form:errors/> element shows form input errors and any other error associated with the form data. As an example, there is a field 'age' in our form which should be an integer and if a user specify any character in the field then conversion will come and that error will be shown in the form.
  • Also in this JSP page, we are using few Spring form tags to generate equivalent HTML form input tags and bind these form fields with corresponding properties of the model class User above, including:
  • <form:input>: generates HTML <input type=”text”> tag.
    <form:password>: generates HTML <input type=”password”> tag.
    <form:select>: generates HTML <select> tag and its items in <option> tags.
    
    

  • Finally, you can find the standard HTML tag <input type="submit" /> that generates a ‘Submit’ button and trigger the sending of data to the server.

success.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Confirmation Page</title>
</head>
<body>
	<h1>Registration has been completed with following details :</h1> <br>
	Name : ${USER.name}.<br>
	Standard : ${USER.email}. <br>
	Age : ${USER.age}.<br>
	Sex : ${USER.sex}.
</body>
</html>

The JSP page is simply using EL expressions to display values of properties of the User object in the model.


Step 10: Creating messages.properties

Create 'messages_en.properties' file inside resources folder and add following entry into this file.

typeMismatch.age= Invalid Entry, Please enter a number.

We will use this file to override conversion error text for the field 'age' and will show a user friendly error message. Here is the error message.


Testing the Application

The 'SpringMVCForm' application can be deployed in a Tomcat server and accessed locally by using below URL.

http://localhost:8080/SpringMVCForm/

This is the view containing the main form before the submit operation:

Spring MVC Form


Now, fill all the fields in form but in the field age enter any alphabet and click on 'Save Changes' button, you will get following error screen.

Spring MVC Form


Then, fill all values correctly and click on 'Save Changes' button you will get following success page with confirmation of values entered.

Spring MVC Form



Download this example developed in eclipse





References:- Spring MVC Documentation






comments powered by Disqus