Announcement Announcement Module
Collapse
No announcement yet.
Problem with sessionForm Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with sessionForm

    I am having a problem getting the SimpleFormController to behave the way I want when I have sessionForm=true. Here is my spring-servlet.xml file:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    
    <beans>
    
        <bean id="mySimpleFormController" class="org.springframework.web.servlet.mvc.SimpleFormController">
          <property name="commandClass"><value>test.TestCommandObject</value></property>
          <property name="formView"><value>test/form</value></property>
          <property name="successView"><value>test/success</value></property>
        </bean>
    
        <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <prop key="/test.do">mySimpleFormController</prop>
                </props>
            </property>
        </bean>
    
        <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
          <property name="resourceLoaderPath"><value>/WEB-INF/vm/</value></property>
          <property name="velocityProperties">
            <props>
              <prop key="resource.loader">file</prop>
              <prop key="file.resource.loader.class">
                org.apache.velocity.runtime.resource.loader.FileResourceLoader
              </prop>
              <prop key="file.resource.loader.path">$&#123;webapp.root&#125;/WEB-INF/vm/</prop>
              <prop key="file.resource.loader.cache">false</prop>
            </props>
          </property>                
        </bean>    
        
        <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
          <property name="exposeSpringMacroHelpers"><value>true</value></property>
          <property name="dateToolAttribute"><value>date</value></property>
          <property name="cache"><value>false</value></property>
          <property name="prefix"><value></value></property>
          <property name="suffix"><value>.vm</value></property>
        </bean>   
        
    </beans>
    test.TestCommandObject is a simple JavaBean with one String property called name. Here is WEB-INF/vm/test/form.vm:

    Code:
    <html>
      <body>
        <form action="" method="POST">
          Name&#58; #springFormInput&#40;"command.name" ""&#41;
          <input type="submit">
        </form>
      </body>
    </html>
    Here is WEB-INF/vm/test/success.vm:

    Code:
    <html>
      <body>
        <h1>Success</h1>
        <a href="/test.do">Back to the Form</a>
      </body>
    </html>
    So, when I go to /test.do in my browser, I get the form. When I enter something and submit the form, it goes the the success page, as expected. When I click on the link on the success page that goes to /test.do, it takes me back to the form, with the name left blank, as expected.

    Now, if I add
    Code:
    <property name="sessionForm"><value>true</value></property>
    to mySimpleFormController, I would expect that after I have submitted my form, once I click on the link to go back to the form, the form would be pre-populated with the same name I entered before, because it should already be stored in the session form. This is not what happens, the form is still blank. Am I doing something wrong? Is this not how session forms are supposed to work?

  • #2
    So I created my own class that extends SimpleFormController and overrides the formBackingObject method like this:

    Code:
    protected Object formBackingObject&#40;HttpServletRequest request&#41; throws Exception &#123;
    		if&#40;isSessionForm&#40;&#41;&#41; &#123;
    			HttpSession session = request.getSession&#40;&#41;;
    			log.debug&#40;"session form attribute is&#58; "+getFormSessionAttributeName&#40;&#41;&#41;;
    			Object object = session.getAttribute&#40;getFormSessionAttributeName&#40;&#41;&#41;;
    			if&#40;object != null&#41; &#123;
    				log.debug&#40;getFormSessionAttributeName&#40;&#41;+"="+object&#41;;
    				return &#40;TestCommandObject&#41;object;
    			&#125; else &#123;
    				log.debug&#40;getFormSessionAttributeName&#40;&#41;+" is null"&#41;;
    			&#125;
    		&#125;
    		return createCommand&#40;&#41;;
    	&#125;
    The first time I issue a GET request to the form, the object is null, as expected:

    Code:
    10886 - DEBUG - MySimpleFormController&#40;&#41;.formBackingObject&#58;17 - session form attribute is&#58; test.MySimpleFormController.form.command
    10886 - DEBUG - MySimpleFormController&#40;&#41;.formBackingObject&#58;23 - test.MySimpleFormController.form.command is null
    But after I enter something, submit the form, and then issue another GET request, the object is still null:

    Code:
    38784 - DEBUG - MySimpleFormController&#40;&#41;.formBackingObject&#58;17 - session form attribute is&#58; test.MySimpleFormController.form.command
    38784 - DEBUG - MySimpleFormController&#40;&#41;.formBackingObject&#58;23 - test.MySimpleFormController.form.command is null
    Why is it null? Shouldn't the controller save the command object to the session the first time I submit the form?

    Comment


    • #3
      Ok, I finally have this figured out. If formSubmission is true (which by default is when the HTTP method is POST), then getCommand (defined in AbstractFormController) is called. getCommand removes the command object from the session. So effectively, every time a form is submitted, the session data is removed. I assume this is because once the form is submitted, spring thinks you don't want the data anymore. I guess in some cases, such as a Multipage Wizard, this makes sense.

      Coming from Struts, I was thinking that Spring's sessionForm=true would be like a session scoped ActionForm in Struts, but that is not the case. In order to get the session form to hang around, you have to put the command object back in the session during onSubmit, like this:

      Code:
      protected ModelAndView onSubmit&#40;HttpServletRequest request, HttpServletResponse response, 
      			Object command, BindException errors&#41; throws Exception &#123;
      		request.getSession&#40;&#41;.setAttribute&#40;getFormSessionAttributeName&#40;&#41;,command&#41;;
      		return onSubmit&#40;command,errors&#41;;
      	&#125;

      Comment

      Working...
      X