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)

Get our Articles via Email. Enter your email address.

You may also like...

31 Comments

  1. Anil Kumar A says:

    very useful tutorial. thanks you.

  2. Ben li says:

    well, how do you handle the validation?

  3. balanza says:

    Hi,

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

    • Viral Patel says:

      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.

  4. Ponic says:

    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?

  5. Swapnil Warekar says:

    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

  6. Renukeswar says:

    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

  7. chimbu says:

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

  8. Zaheer Ahmed says:

    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.

  9. Deenadhayalan says:

    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?

  10. Nox says:

    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.

  11. Roman says:

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

  12. Harpreet says:

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

  13. Dinu says:

    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.

  14. venkat says:

    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().

  15. error says:

    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 / …

  16. jpdave says:

    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.

  17. fariez sang hokage says:

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

  18. Thanks lot of

  19. Jatin Sheth says:

    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 says:

      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).

  20. Rupa Reddy says:

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

  21. Lahiru says:

    Thank you. Helpful!

  22. Neil M says:

    Why did you stop blogging? Your site is great.

  23. Jessa says:

    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.

  24. Can you please help me with Maven in Java

  25. naresh says:

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

  26. prathap says:

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

  27. Annamalai says:

    Nice Article

  28. Civil Machines says:

    awesome…..

Leave a Reply

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