Using Struts' nested indexed properties in a form with table-layout html

Using Struts' nested indexed properties in a form with table-layout

It looks like trying to use Struts’ nested indexed properties in a form with table-layout, with every line (a few formfields) as an editable separate entity, has driven a lot of people (including me) nuts.
With nothing about it in the manual, and no answers to be found on the web, here’s finally a solution.

The JSP:

    <logic:iterate name="orderForm" property="orders" id="rememberMe">
        <html:text name="rememberMe" property="fieldA" indexed="true"/>
    </logic:iterate>

will create a list in HTML like

    <input type="text" name="rememberMe[ 0 ].fieldA">
    <input type="text" name="rememberMe[ 1 ].fieldA">

([0] and [1] being the index, which is added automatically (the ‘indexed=”true”‘ attribute)

The formbean of course needs the collection (assuming there is a Line class/mini-formbean, having fieldA as membervariable with a public getter):

    private List orderLines;
    public List getOrderLines() { return orderLines; }
    public void setOrderLines(List orderLines) { this.orderLines = orderLines; }

but also, here is the trick, a method with a special name that returns an indexed
element (orderline) from the collection of orders:

    public Line getRememberMe(int index) { return (Line)orderLines.get(index); }

As you see, the name of the method needs to correspond with the ‘id’ attribute in the
logic:iterate tag and the ‘name’ attribute in the html:text tag.

This looks like it’s going to work smoothly, but there’s still one problem left.
Everytime a client posts a new request he gets a new (resetted) formbean, so the
collection is not initialized at the moment the form-values will be copied into the bean.
Normally this is ok, but since Struts (or commons.BeanUtils, actually) calls the
“getRememberMe” method to get an element from the collection to set a value in one of
its fields, this can result in a NullPointerException or ArrayIndexOutOfBoundsException.

There are of course multiple solutions for this, among which:

  • If you know the maximum amount of orderlines you will have in your form, you could pre-construct
    them all in the constructor of the formbean, using default values.
  • An automatically growing collection that creates, initializes and adds a new element to
    the collection if the getter is called. This might feel weird at first, but i do think
    it is the best solution. It has the additional plus that a dynamically growing form
    (for example by using the javascript/DOM cloneNode method) will always fit in the collection.

This class could look something like this:

public class AutoGrowingList extends ArrayList
{
    private Class clazz;

    public AutoGrowingList(Class clazz)
    {
        super();
        this.clazz = clazz;
    }

    public Object get(int index)
    {
        Object obj = super.get(index);
        if (obj == null)
        {
            obj = clazz.newInstance();
            super.add(obj);
        }
        return obj;
    }
}

47 Comments

  1. shahija October 28, 2011
  2. duarte August 1, 2011
  3. Siva November 11, 2009
  4. Magali December 28, 2006
  5. Anne June 26, 2006
  6. Anne June 26, 2006
  7. S M June 12, 2006
  8. asgeir June 9, 2006
  9. asgeir June 9, 2006
  10. Jason Hendriks May 18, 2006
  11. Jason Hendriks May 18, 2006
  12. Veera April 5, 2006
  13. Anjali Prabhu March 9, 2006
  14. Rachel February 14, 2006
  15. Jason Hendriks February 10, 2006
  16. Mark Slater January 8, 2006
  17. Mark Slater January 7, 2006
  18. Priya October 26, 2005
  19. sudha September 20, 2005
  20. Steven Line May 26, 2005
  21. pavel April 7, 2005
  22. pavel April 7, 2005
  23. Rahul April 6, 2005
  24. Rahul April 6, 2005
  25. Abu Muinuddin April 6, 2005
  26. Jasper March 17, 2005
  27. Stephen Montgomery March 16, 2005
  28. Adrian Bell March 11, 2005
  29. shuchi February 7, 2005
  30. Mike January 30, 2005
  31. Romina January 30, 2005
  32. Leon van Tegelen January 28, 2005
  33. Vimal Bhatt January 27, 2005
  34. Vimal Bhatt January 27, 2005
  35. Vimal Bhatt January 27, 2005
  36. Jeryl January 3, 2005
  37. Sid Golestane December 14, 2004
  38. Perogi December 11, 2004
  39. Alok Pota December 9, 2004
  40. Perogi December 9, 2004
  41. Alok Pota December 8, 2004
  42. Perogi December 8, 2004
  43. Perogi December 8, 2004
  44. Alok Pota December 8, 2004
  45. Scott Carlson October 29, 2004
  46. Thomas October 4, 2004
  47. Leon van Tegelen September 28, 2004