Announcement Announcement Module
Collapse
No announcement yet.
Can Spring MVC use HashMap command objects instead of Beans? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Can Spring MVC use HashMap command objects instead of Beans?

    Hello everybody,

    I need something like dynamic forms (remotely similar to Apache Cocoon Forms or serverside Xforms): I am trying to develop a very simple data-entry-application based on multiple different forms. But it should be extensible by users without programming (that means only html/xml editing).

    My idea was something along these line:
    - Use form definition (a freemarker template with spring bind tags)
    - Write a generic form controller that subclasses SimpleFormController but uses a HashMap instead of a JavaBean for input values that can take the input of every form. I can not use JavaBeans because they are static and I need to be able to process different forms inside one controller which may have different input fields (number and id of input fields).
    - Build an xml file out of all the input (that is the easy part, since the user will be required to enter an xml input value mapping template also)
    - Save that xml file

    However the notion of the Bean seems to be spread all over Spring MVC.
    And every exception seams to be leading me deeper into the MVC core.

    Let me say that I am just learning Spring. Please forgive me if I ask something that should be obvious for the professional Spring developer, but for me it is not (even after extensive searches and documentation reading).

    I would be very grateful for every hint or suggestion you can give me.

    Thanks in advance.


    My current experiments are:

    action-servlet.xml:

    Code:
    <bean id="genericFormController" class="qammm.GenericFormController">
            <property name="commandName"><value>hashMap</value></property>
            <property name="commandClass"><value>java.util.HashMap</value></property>
            <!-- <property name="validator"><ref bean="beanValidator"/></property> -->
            <property name="formView"><value>genericForm</value></property>
            <property name="successView"><value>redirect&#58;genericForm.html</value></property>
            <property name="userManager"><ref bean="userManager"/></property>
        </bean>
    excerpt from GenericFormController:

    Code:
        protected Object formBackingObject&#40;HttpServletRequest request&#41;
                throws ServletException &#123;
     
        	return new HashMap&#40;&#41;;
        &#125;
        
    	protected ServletRequestDataBinder createBinder&#40;HttpServletRequest request, Object command&#41;
        	throws Exception &#123;
    
    		ServletRequestDataBinder binder = new GenericBinder&#40;command, getCommandName&#40;&#41;&#41;;
    	
    		initBinder&#40;request, binder&#41;;
    		return binder;
    	&#125;
    
       public ModelAndView onSubmit&#40;HttpServletRequest request,
                                     HttpServletResponse response, Object command,
                                     BindException errors&#41;
                throws Exception &#123;
            if &#40;log.isDebugEnabled&#40;&#41;&#41; &#123;
                log.debug&#40;"entering 'onSubmit' method..."&#41;;
            &#125;
            
            HashMap genericData = &#40;HashMap&#41; command;
            Iterator it = genericData.values&#40;&#41;.iterator&#40;&#41;;
            
            for&#40;String s = &#40;String&#41;it.next&#40;&#41;;it.hasNext&#40;&#41;;s =&#40;String&#41; it.next&#40;&#41;&#41; &#123;
            	log.info&#40;s&#41;;
            &#125;
    
            return new ModelAndView&#40;getSuccessView&#40;&#41;&#41;;
        &#125;
    GenericBinder:

    Code:
    public class GenericBinder extends ServletRequestDataBinder &#123;
    
    	public GenericBinder&#40;Object arg0, String arg1&#41; &#123;
    		super&#40;arg0, arg1&#41;;
    		// TODO Auto-generated constructor stub
    	&#125;
    	
    	protected void applyPropertyValues&#40;MutablePropertyValues mpvs&#41; &#123;
    		try &#123;
    			PropertyValue&#91;&#93; pva = mpvs.getPropertyValues&#40;&#41;;
    			HashMap target = &#40;HashMap&#41; this.getTarget&#40;&#41;;
    			for&#40;int i = 0; i < pva.length; i++&#41;&#123;
    				target.put&#40;pva&#91;i&#93;.getName&#40;&#41;, pva&#91;i&#93;.getValue&#40;&#41;&#41;;
    			&#125;
    		&#125;
    		catch &#40;PropertyAccessExceptionsException ex&#41; &#123;
    			// TODO&#58; log out exception
    		&#125;
    	&#125;
    	
    &#125;
    genericForm.ftl (Freemarker template):

    Code:
    <#import "/spring.ftl" as spring/>
    <#assign xhtmlCompliant = true in spring>
    
    <title>generic form</title>
      
    <form method="post" action="genericForm.html">
    
            <@spring.formInput 'hashMap&#91;"first"&#93;', 'id="first"'/>
            <@spring.showErrors "<br>", "fieldError"/>
    
    </form>
    Now I am stuck here getting an exception:

    Java backtrace for programmers:
    ----------
    freemarker.template.TemplateModelException: MethodgetBindStatus on org.springframework.web.servlet.support.RequestCon text
    at freemarker.ext.beans.OverloadedMethodModel.exec(Ov erloadedMethodModel.java:112)
    at freemarker.core.MethodCall._getAsTemplateModel(Met hodCall.java:93)
    at freemarker.core.Expression.getAsTemplateModel(Expr ession.java:89)
    at freemarker.core.Assignment.accept(Assignment.java: 91)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.IfBlock.accept(IfBlock.java:82)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.MixedContent.accept(MixedContent.j ava:92)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.Macro$Context.runMacro(Macro.java: 164)
    at freemarker.core.Environment.visit(Environment.java :470)
    at freemarker.core.UnifiedCall.accept(UnifiedCall.jav a:128)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.MixedContent.accept(MixedContent.j ava:92)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.Macro$Context.runMacro(Macro.java: 164)
    at freemarker.core.Environment.visit(Environment.java :470)
    at freemarker.core.UnifiedCall.accept(UnifiedCall.jav a:128)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.MixedContent.accept(MixedContent.j ava:92)
    at freemarker.core.Environment.visit(Environment.java :171)
    at freemarker.core.Environment.process(Environment.ja va:156)
    at freemarker.template.Template.process(Template.java :219)
    at org.springframework.web.servlet.view.freemarker.Fr eeMarkerView.processTemplate(FreeMarkerView.java:2 67)
    at org.springframework.web.servlet.view.freemarker.Fr eeMarkerView.doRender(FreeMarkerView.java:221)
    at org.springframework.web.servlet.view.freemarker.Fr eeMarkerView.renderMergedTemplateModel(FreeMarkerV iew.java:180)
    at org.springframework.web.servlet.view.AbstractTempl ateView.renderMergedOutputModel(AbstractTemplateVi ew.java:160)
    at org.springframework.web.servlet.view.AbstractView. render(AbstractView.java:247)
    at org.springframework.web.servlet.DispatcherServlet. render(DispatcherServlet.java:839)
    at org.springframework.web.servlet.DispatcherServlet. doDispatch(DispatcherServlet.java:616)
    at org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:543)
    at org.springframework.web.servlet.FrameworkServlet.s erviceWrapper(FrameworkServlet.java:390)
    at org.springframework.web.servlet.FrameworkServlet.d oGet(FrameworkServlet.java:341)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:689)
    at javax.servlet.http.HttpServlet.service(HttpServlet .java:802)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:237)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter .doFilter(UrlRewriteFilter.java:311)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:186)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at com.opensymphony.module.sitemesh.filter.PageFilter .parsePage(PageFilter.java:118)
    at com.opensymphony.module.sitemesh.filter.PageFilter .doFilter(PageFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:186)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at org.appfuse.web.MessageFilter.doFilter(MessageFilt er.java:36)
    at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:186)
    at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:157)
    at org.apache.catalina.core.StandardWrapperValve.invo ke(StandardWrapperValve.java:214)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.StandardContextValve.invo keInternal(StandardContextValve.java:198)
    at org.apache.catalina.core.StandardContextValve.invo ke(StandardContextValve.java:152)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.StandardHostValve.invoke( StandardHostValve.java:137)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:118)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:102)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.StandardEngineValve.invok e(StandardEngineValve.java:109)
    at org.apache.catalina.core.StandardValveContext.invo keNext(StandardValveContext.java:104)
    at org.apache.catalina.core.StandardPipeline.invoke(S tandardPipeline.java:520)
    at org.apache.catalina.core.ContainerBase.invoke(Cont ainerBase.java:929)
    at org.apache.coyote.tomcat5.CoyoteAdapter.service(Co yoteAdapter.java:160)
    at org.apache.coyote.http11.Http11Processor.process(H ttp11Processor.java:799)
    at org.apache.coyote.http11.Http11Protocol$Http11Conn ectionHandler.processConnection(Http11Protocol.jav a:705)
    at org.apache.tomcat.util.net.TcpWorkerThread.runIt(P oolTcpEndpoint.java:577)
    at org.apache.tomcat.util.threads.ThreadPool$ControlR unnable.run(ThreadPool.java:683)
    at java.lang.Thread.run(Thread.java:534)
    Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at freemarker.ext.beans.BeansWrapper.invokeMethod(Bea nsWrapper.java:457)
    at freemarker.ext.beans.OverloadedMethodModel.exec(Ov erloadedMethodModel.java:108)
    ... 68 more
    Caused by: java.lang.IllegalStateException: Neither Errors instance nor plain target object for bean name 'hashMap["first"]' available as request attribute
    at org.springframework.web.servlet.support.BindStatus .<init>(BindStatus.java:138)
    at org.springframework.web.servlet.support.RequestCon text.getBindStatus(RequestContext.java:655)
    ... 74 more[/list]

  • #2
    Got it working, finally...

    After several hours of trial and error I finally got it working myself. In the following lines I will document my solution for users that might have the same problem in the future.

    The first trick is to put the HashMap into a Bean Command ;-)

    Code:
    package org.appfuse.web;
    
    import java.util.HashMap;
    
    public class HashMapCommand &#123;
    	private HashMap hashMap = new HashMap&#40;&#41;;
    		
    	public void setHashMap&#40;HashMap hashMap&#41; &#123;
    		this.hashMap = hashMap;
    	&#125;
    
    	public HashMap getHashMap&#40;&#41; &#123;
    		return this.hashMap;
    	&#125;
    &#125;
    The controller looks like this:

    Code:
    package org.appfuse.web;
    
    import java.util.HashMap;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.validation.BindException;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.SimpleFormController;
    
    public class GenericFormController extends SimpleFormController &#123;
        private final Log log = LogFactory.getLog&#40;GenericFormController.class&#41;;
    
        public ModelAndView onSubmit&#40;HttpServletRequest request,
                                     HttpServletResponse response, Object command,
                                     BindException errors&#41;
                throws Exception &#123;
            if &#40;log.isDebugEnabled&#40;&#41;&#41; &#123;
                log.debug&#40;"entering 'onSubmit' method..."&#41;;
            &#125;
            
            HashMap hashMapData = &#40;&#40;HashMapCommand&#41;command&#41;.getHashMap&#40;&#41;;
            log.info&#40;"content of hashmap&#58; " + hashMapData&#41;;
    
            return new ModelAndView&#40;getSuccessView&#40;&#41;&#41;;
        &#125;
    &#125;
    The JSP looks like this:

    Code:
    <%@ include file="/taglibs.jsp"%>
    
    <title>title</title>
    
    <p>Please fill in user's information below&#58;</p>
      
    <form method="post" action="<c&#58;url value="/genericForm.html"/>" name="genericForm">
    
    <table class="detail">
    <tr>
        <th>fn&#58;</th>
        <td>
            <spring&#58;bind path="hashMapCommand.hashMap&#91;'firstName'&#93;">
            <input type="text" name="$&#123;status.expression&#125;" id="$&#123;status.expression&#125;" value="$&#123;status.value&#125;"/>
            </spring&#58;bind>
        </td>
    </tr>
    <tr>
        <th>ln&#58;</th>
        <td>
            <spring&#58;bind path="hashMapCommand.hashMap&#91;'lastName'&#93;">
            <input type="text" name="$&#123;status.expression&#125;" id="$&#123;status.expression&#125;" value="$&#123;status.value&#125;"/>
            </spring&#58;bind>
        </td>
    </tr>
    
    <tr>
        <td></td>
        <td>
            <input type="submit" class="button" name="save" value="Save"/>
        </td>
    </tr>
    </table>
    </form>

    Comment


    • #3
      I was having the same exact problem. It seems that I do not have my list initialized because I am getting an Index out of bounds exception.

      Since you have fugures this out, do you know what made the difference for you?

      My Command Class is almost the same :

      Class myCommand{
      List X = new ArrayList();
      String y;
      //getters and setters
      }

      Then my jsp is something like :

      <c:forEach item="model.List" var="collection" varStatus="num">
      <spring:bind path="collection.X[${num.index}]">
      <input type="checkbox" name="X" value="yes">
      </spring:bind>
      </c:forEach>


      I am sorry for the poor example, as I dont have the code in front of me right now. That is the jist of what I am doing and apparently it does not think that I have initialized the List at all because it is telling me that I have an out of bound exception.

      I am totally stuck and really new to all of this so maybe someone can offer some help? I have done extensive searches and have not found exactly what I am looking for.

      Comment


      • #4
        A few tips

        Hi Trickle,

        I am just learning Spring so my advice might not be absolutely accurate. I am thinking that the initialisation of command objects is either done automatically by Spring as defined in your action-servlet.xml or explicitly by you by overriding the formBackingMethod in your Controller (you normally would do this to get an non-standard new object of your command=form backing object, e.g. to populate it with data from a db). In my case the sources of my second post and the following action-servlet.xml is all that is needed: so just discard everything in my first post, no binder trickery, no overriden formBackingObject, just the contents of my second post, plus the following action-servlet.xml. I can not comment on arrays (not yet used them), but I think I have seen several references in the forum to this topic, when looking for the solution of my problem. You might be interested in doing a forum search with: bind array

        Code:
            <bean id="genericFormController" class="org.appfuse.web.GenericFormController">
                <property name="commandName"><value>hashMapCommand</value></property>
                <property name="commandClass"><value>org.appfuse.web.HashMapCommand</value></property>
                <!-- <property name="validator"><ref bean="beanValidator"/></property> -->
                <property name="formView"><value>genericForm</value></property>
                <property name="successView"><value>redirect&#58;genericForm.html</value></property>
            </bean>

        Comment


        • #5
          Trickle -
          I'm new to Spring (and JSTL) also so this is disclaimered, but your forEach tag looks a little funny to me.

          Here's an example of a multiple select list that works. The model contains 2 sets of data:
          * 'groups' is a Collection of Group objects populated in the referenceData() method
          * cmdContact is the command object from the Controller; it contains a Set of 'groupMemberships'


          Code:
              
          <select name="groupMemberships"  multiple>
                  <c&#58;forEach var="availGroup" items="$&#123;groups&#125;">
                      <option value="<c&#58;out value="$&#123;availGroup.groupID&#125;"/>"
                      <c&#58;forEach var="memberGroup" items="$&#123;cmdContact.groupMemberships&#125;">
                          <c&#58;if test="$&#123;availGroup.groupID == memberGroup.groupID&#125;"> 
                              SELECTED
                          </c&#58;if>
                      </c&#58;forEach>
                      ><c&#58;out value="$&#123;availGroup.name&#125;"/></option>
                  </c&#58;forEach>
              </select>
          I don't think you're referencing your model correctly.

          The JSTL tag ref might help too - http://java.sun.com/products/jsp/jst...ocs/index.html

          Kent

          Comment


          • #6
            Thanks for the replies guys, I have figured some things out. My first implemenatation was incorrect. I am now doing something like this.

            This is my declared command object in the bean xml file.
            Code:
            public class ScreenDisplays &#123;
               private List screens = new ArrayList&#40;&#41;;
            
            public List getScreens&#40;&#41; &#123;
            	return screens;
            &#125;
            public void setScreens&#40;List s&#41; &#123;
            	this.screens = s;
            &#125;
            &#125;
            I then populate the command List "screens" with Objects of this type, it is my value class to hold the values on the form.

            Code:
            public class ScreenDisplay &#123;
                private String candidateId;
                private String job;
                private String firstName;
                private String middleName;
                private String lastName;
                private String resume;
                private List indexes;
                private String screenIn;    
                private String screenOut;
                private String screenAnother;
                private String memo;
            
            //getters and setters

            Then in my FormController, in the referenceData method, I populate the command objects List "screens" with new objects "ScreenDisplay".


            The form renders and no errors are thrown, but when I log what is actually in the list I see the DisplayScreen objects, but the values in the ScreenDisplay objects are not populated. I am definetely binding to them with the following code :

            Code:
            <spring&#58;bind path="ScreenDisplays.screens&#91;$&#123;num.index&#125;&#93;.candidateId">  
                       <input name="candidateId" type="hidden" value="$&#123;sd.candidateId&#125;"> 
                        $&#123;sd.candidateId&#125;
            </spring&#58;bind>

            I have no idea why it is not setting the values for my objects. I am completely stuck. Any help would be awesome!!!!!

            Thanks guys!

            Comment


            • #7
              No help?? :cry:

              Come on guys!

              Comment


              • #8
                value="${sd.candidateId}" won't work I believe.

                Since you are binding it how about value="<c:out value="${status.value}" />" ??

                Comment


                • #9
                  Hi I tried your example but it did nt worked for me



                  Originally posted by qammm
                  After several hours of trial and error I finally got it working myself. In the following lines I will document my solution for users that might have the same problem in the future.

                  The first trick is to put the HashMap into a Bean Command ;-)

                  Code:
                  package org.appfuse.web;
                  
                  import java.util.HashMap;
                  
                  public class HashMapCommand {
                  	private HashMap hashMap = new HashMap();
                  		
                  	public void setHashMap(HashMap hashMap) {
                  		this.hashMap = hashMap;
                  	}
                  
                  	public HashMap getHashMap() {
                  		return this.hashMap;
                  	}
                  }
                  The controller looks like this:

                  Code:
                  package org.appfuse.web;
                  
                  import java.util.HashMap;
                  import javax.servlet.http.HttpServletRequest;
                  import javax.servlet.http.HttpServletResponse;
                  
                  import org.apache.commons.logging.Log;
                  import org.apache.commons.logging.LogFactory;
                  import org.springframework.validation.BindException;
                  import org.springframework.web.servlet.ModelAndView;
                  import org.springframework.web.servlet.mvc.SimpleFormController;
                  
                  public class GenericFormController extends SimpleFormController {
                      private final Log log = LogFactory.getLog(GenericFormController.class);
                  
                      public ModelAndView onSubmit(HttpServletRequest request,
                                                   HttpServletResponse response, Object command,
                                                   BindException errors)
                              throws Exception {
                          if (log.isDebugEnabled()) {
                              log.debug("entering 'onSubmit' method...");
                          }
                          
                          HashMap hashMapData = ((HashMapCommand)command).getHashMap();
                          log.info("content of hashmap: " + hashMapData);
                  
                          return new ModelAndView(getSuccessView());
                      }
                  }
                  The JSP looks like this:

                  Code:
                  <%@ include file="/taglibs.jsp"%>
                  
                  <title>title</title>
                  
                  <p>Please fill in user's information below:</p>
                    
                  <form method="post" action="<c:url value="/genericForm.html"/>" name="genericForm">
                  
                  <table class="detail">
                  <tr>
                      <th>fn:</th>
                      <td>
                          <spring:bind path="hashMapCommand.hashMap['firstName']">
                          <input type="text" name="${status.expression}" id="${status.expression}" value="${status.value}"/>
                          </spring:bind>
                      </td>
                  </tr>
                  <tr>
                      <th>ln:</th>
                      <td>
                          <spring:bind path="hashMapCommand.hashMap['lastName']">
                          <input type="text" name="${status.expression}" id="${status.expression}" value="${status.value}"/>
                          </spring:bind>
                      </td>
                  </tr>
                  
                  <tr>
                      <td></td>
                      <td>
                          <input type="submit" class="button" name="save" value="Save"/>
                      </td>
                  </tr>
                  </table>
                  </form>

                  Comment


                  • #10
                    how do i put hashmap within hashmap?

                    friends,

                    i am new to Spring , found ur example fantastic and its working lovely.


                    if i want to put hashmap within hashmap, what do i do?

                    plz give me some code example?

                    thanks a million friends

                    Comment


                    • #11
                      Hi Gammm,

                      Would like to know if this will work with Spring MVC Portlet? Has anyone try something similar to this approach?





                      Originally posted by qammm View Post
                      After several hours of trial and error I finally got it working myself. In the following lines I will document my solution for users that might have the same problem in the future.

                      The first trick is to put the HashMap into a Bean Command ;-)

                      Code:
                      package org.appfuse.web;
                      
                      import java.util.HashMap;
                      
                      public class HashMapCommand {
                      	private HashMap hashMap = new HashMap();
                      		
                      	public void setHashMap(HashMap hashMap) {
                      		this.hashMap = hashMap;
                      	}
                      
                      	public HashMap getHashMap() {
                      		return this.hashMap;
                      	}
                      }
                      The controller looks like this:

                      Code:
                      package org.appfuse.web;
                      
                      import java.util.HashMap;
                      import javax.servlet.http.HttpServletRequest;
                      import javax.servlet.http.HttpServletResponse;
                      
                      import org.apache.commons.logging.Log;
                      import org.apache.commons.logging.LogFactory;
                      import org.springframework.validation.BindException;
                      import org.springframework.web.servlet.ModelAndView;
                      import org.springframework.web.servlet.mvc.SimpleFormController;
                      
                      public class GenericFormController extends SimpleFormController {
                          private final Log log = LogFactory.getLog(GenericFormController.class);
                      
                          public ModelAndView onSubmit(HttpServletRequest request,
                                                       HttpServletResponse response, Object command,
                                                       BindException errors)
                                  throws Exception {
                              if (log.isDebugEnabled()) {
                                  log.debug("entering 'onSubmit' method...");
                              }
                              
                              HashMap hashMapData = ((HashMapCommand)command).getHashMap();
                              log.info("content of hashmap: " + hashMapData);
                      
                              return new ModelAndView(getSuccessView());
                          }
                      }
                      The JSP looks like this:

                      Code:
                      <%@ include file="/taglibs.jsp"%>
                      
                      <title>title</title>
                      
                      <p>Please fill in user's information below:</p>
                        
                      <form method="post" action="<c:url value="/genericForm.html"/>" name="genericForm">
                      
                      <table class="detail">
                      <tr>
                          <th>fn:</th>
                          <td>
                              <spring:bind path="hashMapCommand.hashMap['firstName']">
                              <input type="text" name="${status.expression}" id="${status.expression}" value="${status.value}"/>
                              </spring:bind>
                          </td>
                      </tr>
                      <tr>
                          <th>ln:</th>
                          <td>
                              <spring:bind path="hashMapCommand.hashMap['lastName']">
                              <input type="text" name="${status.expression}" id="${status.expression}" value="${status.value}"/>
                              </spring:bind>
                          </td>
                      </tr>
                      
                      <tr>
                          <td></td>
                          <td>
                              <input type="submit" class="button" name="save" value="Save"/>
                          </td>
                      </tr>
                      </table>
                      </form>

                      Comment

                      Working...
                      X