Spring MVC HashMap Form Integration example

Spring MVC provides powerful way to manage form inputs. It also provides form validation functionality which is easy to integrate in any application. But other than the normal form bean mapping, recently I had a requirement to map dynamic values like key-value pairs in an HTML form and retrieve the same in Spring Controller. So basically HashMap came to rescue.

Let us see how to map a key-value pair based HashMap in a Spring command object using Spring MVC. The example will show a simple form which renders a Map.

Related: Spring 3 MVC Tutorial Series (Must Read)

Tools and Technologies used:

  1. Java 5 or above
  2. Eclipse 3.3 or above
  3. Spring MVC 3.0

Step 1: Create Project Structure

Open Eclipse and create a Dynamic Web Project.
eclipse-dynamic-web-project

Enter project name as SpringMVC_Hashmap and press Finish.

Step 2: Copy Required JAR files

Once the Dynamic Web Project is created in Eclipse, copy the required JAR files under WEB-INF/lib folder. Following are the list of JAR files:
spring-hashmap-form-jar-files

Don’t worry if you dont have these JARs. You can download all the JAR files with complete source code at the end of this tutorial.


Step 3: Adding Spring MVC support

Once the basic project setup is done, we will add Spring 3 MVC support. For that first modify default web.xml and add springs DispatcherServlet.

File: /WebContent/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>Spring3MVC-Hashmap</display-name>
	<servlet>
		<servlet-name>spring</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>
</web-app>

Related: Tutorial: Learn Spring MVC Lifecycle

Now add spring-servlet.xml file under WEB-INF folder.

File: /WebContent/WEB-INF/spring-servlet.xml

 
<?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
		
	<context:annotation-config />
	<context:component-scan base-package="net.viralpatel.spring3.controller" />	

	<bean id="jspViewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass"
			value="org.springframework.web.servlet.view.JstlView" />
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

Note that in above spring-servlet file, line 10, 11 defines context:annotation-config and component-scan tags. These tags let Spring MVC knows that the spring mvc annotations are used to map controllers and also the path from where the controller files needs to be loaded. All the files below package net.viralpatel.spring3.controller will be picked up and loaded by spring mvc.

Step 4: Add Spring Controller and Form classes

File: /src/net/viralpatel/spring3/form/ContactForm.java

package net.viralpatel.spring3.form;

import java.util.HashMap;
import java.util.Map;

public class ContactForm {

	private Map<String, String> contactMap = new HashMap<String, String>();

	public Map<String, String> getContactMap() {
		return contactMap;
	}

	public void setContactMap(Map<String, String> contactMap) {
		this.contactMap = contactMap;
	}

}

Note line 8 in above code how we have defined a HashMap which will hold the key-value pair data.

File: /src/net/viralpatel/spring3/controller/ContactController.java

package net.viralpatel.spring3.controller;

import java.util.HashMap;
import java.util.Map;

import net.viralpatel.spring3.form.ContactForm;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ContactController {

	private static Map<String, String> contactMap = new HashMap<String, String>();
	static {
		contactMap.put("name", "John");
		contactMap.put("lastname", "Lennon");
		contactMap.put("genres", "Rock, Pop");
	}
	
	@RequestMapping(value = "/show", method = RequestMethod.GET)
	public ModelAndView get() {
		
		ContactForm contactForm = new ContactForm();
		contactForm.setContactMap(contactMap);
		
		return new ModelAndView("add_contact" , "contactForm", contactForm);
	}
	
	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public ModelAndView save(@ModelAttribute("contactForm") ContactForm contactForm) {
		
		return new ModelAndView("show_contact", "contactForm", contactForm);
	}
}

In above ContactController class, we have defile two methods: get() and save().

get() method: This method is used to display Contact form with pre-populated values. Note we added a map of contacts (Contacts map is initialized in static block) in ContactForm bean object and set this inside a ModelAndView object. The add_contact.jsp is displayed which in turns display all contacts in tabular form to edit.

save() method: This method is used to fetch contact data from the form submitted and save it in the static map. Also it renders show_contact.jsp file to display contacts in tabular form.

Step 5: Add JSP View files

Add following files under WebContent/WEB-INF/jsp/ directory.

File: /WebContent/WEB-INF/jsp/add_contact.jsp

<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
	<title>Spring 3 MVC HashMap Form - viralpatel.net</title>
</head>
<body>

<h2>Spring 3 MVC HashMap Form</h2>
<form:form method="post" action="add.html" modelAttribute="contactForm">
	<table>
	<tr>
		<th>Key</th>
		<th>Value</th>
	</tr>
	<c:forEach items="${contactForm.contactMap}" var="contactMap" varStatus="status">
		<tr>
			<td>${contactMap.key}</td>
			<td><input name="contactMap['${contactMap.key}']" value="${contactMap.value}"/></td>
		</tr>
	</c:forEach>
</table>	
<br/>

<input type="submit" value="Save" />
	
</form:form>
</body>
</html>

In above JSP file, we display contact details map in a table. Also each attribute is displayed in a textbox. Note that modelAttribute=”contactForm” is defined in
tag. This tag defines the modelAttribute name for Spring mapping. On form submission, Spring will parse the values from request and fill the ContactForm bean and pass it to the controller.

Also note how we defined textboxes name. It is in form contactMap['key']. Thus Spring knows that we want to display the Map item with key key.

contactMap['${contactMap.key}'] will generate each rows as follows:

contactMap['name'] // mapped to key ‘name’ in hashmap contactMap
contactMap['lastname'] // mapped to key ‘lastname’ in hashmap contactMap
contactMap['genres'] // mapped to key ‘genres’ in hashmap contactMap

Here we used JSTL to iterate through an HashMap.

Spring 3 MVC and path attribute and square bracket

One thing here is worth noting that we haven’t used Spring’s
tag to render textboxes. This is because Spring MVC 3 has a unique way of handling path attribute for
tag. If we define the textbox as follows:

<form:input path="contactMap['${contact.key}']" />

Then instead of converting it to following HTML code:

<input name="contactMap['name']" />
<input name="contactMap['firstname']" />
<input name="contactMap['genres']" />

It converts it into following:

<input name="contactMap'name'" />
<input name="contactMap'firstname'" />
<input name="contactMap'genres'" />

Note how it removed square brackets [ ] from name attribute. In previous versions of Spring (before 2.5) the square bracket were allowed in name attribute.

It seems w3c has later changed the HTML specification and removed [ ] from html input name.
Read the specification http://www.w3.org/TR/html4/types.html#type-name. It clearly says that:

ID and NAME tokens must begin with a letter ([A-Za-z]) and may be followed by any number of letters, digits ([0-9]), hyphens (“-”), underscores (“_”), colons (“:”), and periods (“.”).

Thus, square brackets aren’t allowed in name attribute! And thus Spring 3 onwards this was implemented.

So far I haven’t got any workaround to use springs <form:input /> tag instead of plain html <input /> to render and fetch data from multiple rows.

File: /WebContent/WEB-INF/jsp/show_contact.jsp

<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Spring 3 MVC HashMap Form - viralpatel.net</title>
</head>
<body>
	<h2>Show Contact</h2>
	<table>
		<tr>
			<th>Key</th>
			<th>Value</th>
		</tr>
		<c:forEach items="${contactForm.contactMap}" var="contactMap"
			varStatus="status">
			<tr>
				<td>${contactMap.key}</td>
				<td>${contactMap.value}</td>
			</tr>
		</c:forEach>
	</table>
	<br />
	<input type="button" value="Back" onclick="javascript:history.back()" />
</body>
</html>

File: /WebContent/index.jsp

<jsp:forward page="show.html"></jsp:forward>


Final Project Structure

Once we have added all relevant source files and jar files, the project structure should look like following:
spring-hashmap-form-project-structure


Step 6: Execute it

Execute the web application Right click on project > Run As > Run on Server.

Add Contact page
spring-hashmap-form-demo-contact

Show Contact page
spring-hashmap-form-demo-show

Download Source Code

SpringMVC_Hashmap.zip (2.8 MB)



29 Comments

  • Anil Kumar A 26 September, 2012, 23:06

    very useful tutorial. thanks you.

  • Ben li 27 September, 2012, 1:20

    well, how do you handle the validation?

  • balanza 2 November, 2012, 2:21

    Hi,

    I’ve followed every step, but once I ran the application it comes out with 404 errors. Any idea of why?

    • Viral Patel 5 November, 2012, 16:35

      Hi, Please check if you errors in server logs. Most of the time when application is not compiled and the classes folder is not updated in WEB-INF/ of your server root, this error comes.

  • Ponic 23 November, 2012, 1:38

    It is better to keep the jar files in WEB-IF/lib folder or
    -Right click –> web project –> PROPERTIES
    - Choose the J2EE Module Dependencies
    - Click on the Add External JARs… and then point on your library file (ZIP or JAR)

    which is recommended method?

  • Swapnil Warekar 30 November, 2012, 20:38

    Hi,
    its nice example, You have explained in very good manner and can be understand easily.

    I tried to change the this example by using ArrayList and having checkboxes instead of input texts. But my modelattribute is not populating my list at controller when I submits by clicking some checkboxes.

    What should be the value name attribute for list as in your example for map name=”contactMap['${contactMap.key}']“?

    Thank you,

    Swapnil

  • Renukeswar 3 December, 2012, 16:22

    Iam new to Spring 3 , it is good tutorial to learn basics but for Data is not coming up in the jsp which is set in Controller.please tell me how can i get the data in jsp , i used the same code

  • chimbu 5 December, 2012, 13:13

    The coding was very helpful to me …. and thank u so much friend……

  • Zaheer Ahmed 19 December, 2012, 15:00

    Any example of saving a foreign key value by using spring form ? e.g. let’s say you have one Category to many Products. After saving categories when you come to save a product you’ll have categories as a dropdown list, so you’ll be saving a product with category id as a foreign key.

  • Deenadhayalan 22 January, 2013, 11:38

    Iam using netbeans 7.0,created web project,1 dout..u r using spring-servlet.xml right..?what is the use of that file, where u including in the project?did u telling that file’s path in web.xml any?

  • Nox 28 January, 2013, 14:12

    Hi Viral, very great tutorial. I have followed all the steps and was able to manipulate the code too. Right now I have to do something similar to this, however I have a config (XML) file that I am currently reading from. I need to have the same kind of a form and have someone add data and click the save button, then the data is written in XML to the config file(not removing the old data, but adding to it. The config file should change and remain what it has been changed to even if the browser was closed and opened again. Also if you could have the functionality to delete from the config file it would be great.

    Thanks in advance.

  • Roman 1 February, 2013, 13:52

    Thanks a lot!
    Your tutorials are easy to understand, and are very useful!
    You saved a lot of my time!
    Thanks again!

  • Harpreet 4 February, 2013, 13:16

    HTTP Status 404 – /SpringIntegration/show.html on running same example…. please help

  • Dinu 20 February, 2013, 12:56

    Please mention how to perform validation in this example. This issue has been troubling a lot.
    What is the path need to be mentioned for form:errors tag . And what is the key need to be used inside the Validator.

  • venkat 26 February, 2013, 15:22

    Hi it is a good tutorial to learn spring annotations basics But . data is not coming in the jsp which is set in Controller Class.can you please tell me know how can i display the data in jsp , i used the same code,It is not workout.But I can able to get the data through request.setAttribute().

  • error 11 March, 2013, 2:18

    most people get error, could you correct it ? 404 error , can not find hello page , even i change the “hello.html” or patten to be / …

  • jpdave 11 March, 2013, 12:02

    hello all,
    Thanks in advance.
    i am new to roo and jspx . i have created the mvc based project with roo . but when i try to display foriegn key value in a table it dispays all the fields values of the primery key table. i only want to dispay only 1 field value.

  • fariez sang hokage 13 March, 2013, 12:26

    IF U show 404 errors.
    fix contactcontroller.java
    wrong -> @RequestMapping(value = “/show”, method = RequestMethod.GET)
    FIX -> @RequestMapping(value = “/”, method = RequestMethod.GET)

  • Sandeep Kumar Bharti 23 September, 2013, 11:53

    Thanks lot of

  • Jatin Sheth 25 September, 2013, 21:26

    Hi Viral,

    I followed same approch but it didn’t work for me.I have following hashMap in form.

    private Map volumnGoalMap;.

    I can iterate and display content on jsp but when i update the same and submit to save changes, the form is not populated with HashMap.HashMap in form in for is empty.

    Your help will be appreciated.

    • Jatin Sheth 25 September, 2013, 21:29

      due to some reason my hashmap key and value is not displayed in comments.So i am explaining…i have hashMap with key as String and value as ManageGoalForm (object).

  • Rupa Reddy 1 October, 2013, 16:22

    It is very useful… thank you So much .. :) :)

  • Lahiru 25 October, 2013, 10:55

    Thank you. Helpful!

  • Neil M 10 December, 2013, 1:21

    Why did you stop blogging? Your site is great.

  • Jessa 13 January, 2014, 6:44

    Hi,
    I tried your tutorial, my program was doing well at first i can show the data in the input fields but when i click on show to display/submit content my hashmap doesn’t have any value in it.

  • Apoorv Dwivedi 27 January, 2014, 19:29

    Can you please help me with Maven in Java

  • naresh 5 February, 2014, 19:54

    hi viralpatel your tutorial is good ,but if you known guidewire &gosu language sample project send me .plzzzz

  • prathap 5 May, 2014, 14:46

    It is extremely useful example thanx for posting, good to see variety of concepts form you

Leave a Reply

Your email address will not be published. Required fields are marked *

Note

To post source code in comment, use [code language] [/code] tag, for example:

  • [code java] Java source code here [/code]
  • [code html] HTML here [/code]

Current ye@r *