Announcement Announcement Module
Collapse
No announcement yet.
Collections (ArrayList), web flow forms, and data binding Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Collections (ArrayList), web flow forms, and data binding

    G'day All,

    I have a requirement to retrieve a list of objects from the database, display them in a 'multi-record' form so that they can be edited, and then save the modified records back to the database. I have set up a web flow to retrieve the records from the database, and then present them to the user in a form. I am having problems binding the data to the form. I am also not sure how to access the data after it has been posted.

    I have read a large number of threads on this forum and experimented with different syntax in the JSP file but still cannot render a JSP containing a form with the data bound.

    I am using Spring v2.5 and Spring Web Flow v1.0.5.

    Spring beans config:

    Code:
        <bean id="viewResolver"
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" 
                      value="org.springframework.web.servlet.view.tiles.TilesJstlView" />
        </bean>
        
        <bean id="urlMapping"
              class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="mappings">
                <props>
                    <prop key="flow.htm">flowController</prop>
                </props>
            </property>
        </bean>
        
        <bean id="tilesConfigurer" 
              class="org.springframework.web.servlet.view.tiles.TilesConfigurer">
            <property name="definitions">
                <list>
                    <value>/WEB-INF/foo-tiles.xml</value>
                </list>
            </property>
        </bean>
        
        <bean id="flowController" 
              class="org.springframework.webflow.executor.mvc.FlowController">
            <property name="flowExecutor" ref="flowExecutor" />
        </bean>
        
        <flow:executor id="flowExecutor" registry-ref="flowRegistry" />
        
        <flow:registry id="flowRegistry">
            <flow:location path="/WEB-INF/flow/**/*-flow.xml" />
        </flow:registry>
        
        <bean id="retrieveRelationshipTypesAction"
              class="foo.action.RetrieveRelationshipTypesAction">
        </bean>
        
        <bean id="saveRelationshipTypeAction"
              class="foo.action.SaveRelationshipTypeAction"/>
        
        <bean id="relationshipTypeFormAction"
              class="foo.form.RelationshipTypeFormAction">
            <property name="formObjectName" value="rtList"/>
            <property name="formObjectScope" value="REQUEST" />
            <property name="formObjectClass" value="java.util.ArrayList"/>
        </bean>
    Web flow definition:

    Code:
        <var name="relationshipTypes" class="java.util.ArrayList" scope="flow" />
        
        <start-state idref="retrieveRelationshipTypes" />
        
        <action-state id="retrieveRelationshipTypes">
            <action bean="retrieveRelationshipTypesAction" />
            <transition on="success" to="showRelationshipTypes" />
        </action-state>
        
        <view-state id="showRelationshipTypes" view="relationshipType.page" >
            <render-actions>
                <action bean="relationshipTypeFormAction" method="setupForm"/>
                <action bean="relationshipTypeFormAction" method="populateList"/>
            </render-actions>
            <transition on="select" to="saveRelationshipType" >
                <action bean="relationshipTypeFormAction" method="bind" />
                <evaluate-action expression="requestScope.pgOfRelTypes">
                    <evaluation-result name="flowScope.relationshipTypes" />
                </evaluate-action>
            </transition>
        </view-state>
        
        <action-state id="saveRelationshipType">
            <action bean="saveRelationshipTypeAction" />
            <transition on="success" to="showRelationshipTypes" />
        </action-state>
    My action form class is:

    Code:
    package foo.form;
    
    import...
    
    public class RelationshipTypeFormAction extends FormAction {
    
        private static Logger log = Logger.getLogger(RelationshipTypeFormAction.class);
    
        public Event populateList(RequestContext context) throws Exception {
            log.debug("populateList: in");
            ArrayList<ItemRelationshipType> relationshipTypes = (ArrayList<ItemRelationshipType>) context.getFlowScope().get("relationshipTypes");
            ArrayList<ItemRelationshipType> rtList = (ArrayList<ItemRelationshipType>) getFormObject(context);
            rtList.clear();
            rtList.addAll(relationshipTypes);
            log.debug("populateList: out");
            return success();
        }
    }
    JSP page (I'm using tiles):

    Code:
    <jsp:directive.include file="/WEB-INF/page/tags.jsp" />
    
    <h3>Relationship Types</h3>
    
    <form:form action="flow.htm" commandName="rtList">
        <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
        <input type="hidden" name="targetAction" value="error">
        <table width="80%">
            <tr>
                <td>
                    ID
                </td>
                <td>
                    Name
                </td>
                <td>
                    Description
                </td>
            </tr>
            
            <c:forEach items="${rtList}" var="rt" varStatus="loop">
                <tr>
                    <td>
                        <%-- <c:out value="${rt.itemRelationshipTypeId}" /> --%>
                        <form:input path="${rtList}[${loop.index}].itemRelationshipTypeId" />
                    </td>
                    <td>
                        <%-- <c:out value="${rt.name}" /> --%>
                        <form:input path="${rtList}[${loop.index}].name" />
                    </td>
                    <td>
                        <%-- <c:out value="${rt.description}" /> --%>
                        <form:input path="${rtList}[${loop.index}].description" />
                    </td>
                </tr>
            </c:forEach>
            
        </table>
        <p>
            <input type="submit" name="_eventId_cancel" value="Cancel"/>
            <input type="submit" name="_eventId_save" value="Save"/>
        </p>
    </form:form>
    When this JSP is called I get this error:

    Code:
    17:14:11,225 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] ERROR org.springframework.web.servlet.tags.form.InputTag - Invalid property '[foo.model.ItemRelationshipType@79b022, foo.model.ItemRelationshipType@79b00e, foo.model.ItemRelationshipType@79affa][0]' of bean class [java.util.ArrayList]: Bean property '[foo.model.ItemRelationshipType@79b022, foo.model.ItemRelationshipType@79b00e, foo.model.ItemRelationshipType@79affa][0]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    org.springframework.beans.NotReadablePropertyException: Invalid property '[foo.model.ItemRelationshipType@79b022, foo.model.ItemRelationshipType@79b00e, foo.model.ItemRelationshipType@79affa][0]' of bean class [java.util.ArrayList]: Bean property '[foo.model.ItemRelationshipType@79b022, foo.model.ItemRelationshipType@79b00e, foo.model.ItemRelationshipType@79affa][0]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    	at org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:544)
    	at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:451)
    	at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:428)
    	...
    Can anyone tell me what the correct syntax is for binding to a list? I've tried several variations on what I've presented here but with no success.

    Thanks, John

  • #2
    You cannot use a List as a formBackingObject. You can use an object containing a List. The samples shipped with Spring provide a working sample of that.

    Comment


    • #3
      Marten, Thanks for your suggestion. I now have the binding working OK. Regards, John

      For future reference the syntax for binding in the JSP is:

      Code:
      <jsp:directive.include file="/WEB-INF/page/tags.jsp" />
      
      <h3>Relationship Types</h3>
      
      <form:form action="flow.htm" commandName="relationshipTypeForm">
          <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
          <input type="hidden" name="targetAction" value="error">
          <table width="80%">
              <tr>
                  <td>
                      ID
                  </td>
                  <td>
                      Name
                  </td>
                  <td>
                      Description
                  </td>
              </tr>
              
              <c:forEach items="${relationshipTypeForm.rtList}" var="rt" varStatus="loop">
                  <tr>
                      <td>
                          <%-- <c:out value="${rt.itemRelationshipTypeId}" /> --%>
                          <form:input path="rtList[${loop.index}].itemRelationshipTypeId" />
                      </td>
                      <td>
                          <%-- <c:out value="${rt.name}" /> --%>
                          <form:input path="rtList[${loop.index}].name" />
                      </td>
                      <td>
                          <%-- <c:out value="${rt.description}" /> --%>
                          <form:input path="rtList[${loop.index}].description" />
                      </td>
                  </tr>
              </c:forEach>
              
          </table>
          <p>
              <input type="submit" name="_eventId_cancel" value="Cancel"/>
              <input type="submit" name="_eventId_save" value="Save"/>
          </p>
      </form:form>

      Comment


      • #4
        How are you applying validation to this? How do you refer to the indexed list in your validator?

        Comment


        • #5
          Originally posted by Marten Deinum View Post
          You cannot use a List as a formBackingObject. You can use an object containing a List. The samples shipped with Spring provide a working sample of that.
          Could you please provide the URL for the samples you have referred in your comment

          Comment

          Working...
          X