Uploaded image for project: 'Spring Web Flow'
  1. Spring Web Flow
  2. SWF-990

Binding to properties of objects in a collection of dynamic size fails with IndexOutOfBoundsException




      Binding to properties of objects in a dynamically sized collection (e.g. AutoPopulatingList, LazyList, GrowthList, etc.) fail with webflow and jboss-el. It looks like org.jboss.el.ValueExpressionImpl.setValue() gets invoked for any additional items but the invocation results in an IndexOutOfBoundsException.

      Our web form allows questions to be added or removed client-side using JavaScript. Each question has a couple of properties that we want to bind to.

      For example, an input for question 3 (at index 2) would look like this:
      <input name="command.questions[2].title" type="text"/>

      In this example "command" is our root binding object, which contains a list of "questions", each of which have a "title" property. We have addressed this with Spring MVC by using a LazyList (commons class, same as AutoPopulatingList) or by using a GrowingList (commons class). These override get/set methods on the List interface to automatically create questions as needed by the binding code.

      However, the EL binding code used by webflow doesn't simply call "get" or "set" on the list, but instead it calls size() and throws an exception if the size isn't large enough. (this is down in ListELResolver) In the previous example, since on the first binding, the questions list would be empty, the EL binding code calls size() which returns 0. Since we're trying to bind to a question at index 2, the binding code throws a PropertyNotFoundException.

      A workaround is to pre-populate the list of questions, but since the client-side DHTML can add or remove those, it's impossible to know how many will be needed for binding (hence our use of Lazy/GrowingList). Perhaps we could hack something together that passes the total number to the server in a hidden field, etc. but I'm not even sure how to hook into the web code prior to binding to do this. (is there a hook into the binding before the EL binding code runs? i.e. the ability to add objects into the collection before webflow tries to bind to the command object)

      I should also mention that binding to a collection of simple properties works fine. For example if my binding was just to "command.questions[3]" you could use a GrowthList. In this case the binding code calls questions.set( 3, "value") and the growth list automatically grows the size of the list to support this. However, "command.questions[3].title" does not work.




            kdonald Keith Donald
            jhaile Jeremy Haile
            14 Vote for this issue
            11 Start watching this issue