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

  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.

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:

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>
Code language: HTML, XML (xml)

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>
Code language: HTML, XML (xml)

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; } }
Code language: Java (java)

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); } }
Code language: Java (java)

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>
Code language: HTML, XML (xml)

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 keycontactMap['${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}']" />
Code language: HTML, XML (xml)

Then instead of converting it to following HTML code:

<input name="contactMap['name']" /> <input name="contactMap['firstname']" /> <input name="contactMap['genres']" />
Code language: HTML, XML (xml)

It converts it into following:

<input name="contactMap'name'" /> <input name="contactMap'firstname'" /> <input name="contactMap'genres'" />
Code language: HTML, XML (xml)

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>
Code language: HTML, XML (xml)

File: /WebContent/index.jsp

<jsp:forward page="show.html"></jsp:forward>
Code language: HTML, XML (xml)

Final Project Structure

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

Step 6: Execute it

Execute the web application Right click on project > Run As > Run on ServerAdd Contact page

Show Contact page

Download Source Code

SpringMVC_Hashmap.zip (2.8 MB)

View Comments

  • Hi,

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

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

  • 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?

  • 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

  • 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

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

  • 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?

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

Share
Published by
Viral Patel
Tags: form html form Spring spring beans spring mvc spring-3-mvc-series

Recent Posts

  • Java

Java URL Encoder/Decoder Example

Java URL Encoder/Decoder Example - In this tutorial we will see how to URL encode/decode…

4 years ago
  • General

How to Show Multiple Examples in OpenAPI Spec

Show Multiple Examples in OpenAPI - OpenAPI (aka Swagger) Specifications has become a defecto standard…

4 years ago
  • General

How to Run Local WordPress using Docker

Local WordPress using Docker - Running a local WordPress development environment is crucial for testing…

4 years ago
  • Java

Create and Validate JWT Token in Java using JJWT

1. JWT Token Overview JSON Web Token (JWT) is an open standard defines a compact…

4 years ago
  • Spring Boot

Spring Boot GraphQL Subscription Realtime API

GraphQL Subscription provides a great way of building real-time API. In this tutorial we will…

4 years ago
  • Spring Boot

Spring Boot DynamoDB Integration Test using Testcontainers

1. Overview Spring Boot Webflux DynamoDB Integration tests - In this tutorial we will see…

4 years ago