Quantcast
Channel: Spring 3 MVC – ViralPatel.net
Viewing all articles
Browse latest Browse all 10

Spring MVC HashMap Form Integration example

$
0
0

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.

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

spring-hashmap-form-project-structure

Step 6: Execute it

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

spring-hashmap-form-demo-contact

Show Contact page

spring-hashmap-form-demo-show

Download Source Code

SpringMVC_Hashmap.zip (2.8 MB)


Viewing all articles
Browse latest Browse all 10

Trending Articles