Thursday, September 10, 2009

Binding Tabular Data with SpringFormControllers

This blog discusses the nature of dynamic tabular data in web applications and how this is handled in Spring Framework. The main point here is that the tabular data cannot be modified in any way or else an IndexOutOfBoundsException will occur.

Assume for a moment that we have tabular data we want to edit the quantity on our cart items. The tabular field is indexed using open and closing square brackets [].

<c:forEach var="item" items="${shoppingCartForm.items}" varStatus="s">
    <spring:bind path="shoppingCart.items[${s.count-1}].quantity">
    <input type="text" name="${status.expression}" value="${status.value}"
        style="width: 100%;"/>

The formBackingObject() method

Override SimpleFormController's formBackingObject() method in your form controller class:

protected Object formBackingObject(HttpServletRequest request) throws Exception {
    Long cartId = RequestUtils.getRequiredLongParameter(request, "cartId");
    ShoppingCart cart = shoppingCartManager.findShoppingCart(cartId);
    return new ShoppingCartCommand(cart);

The Detailed Explanation

When spring binds the array it expects items to have contents. Therefore, we need to override the SimpleFormController.formBackingObject to always retrieve the current data.

During the form rendering (showForm()) our page is rendered and the moment the Controller processes the request after the form is submitted, the controller will retrieve the most current data via the SimpleFormController.formBackingObject().

If for some reason the shopping cart items increased (via some method in the JSP) the binding will throw an IndexOutOfBoundsException because the items currently in our database will be less than what we are trying to bind.

If we have this situation we need to explicitly correlate the number of items to be persisted with the ShoppingCartCommand.items to avoid the exception.

Number of items from the database: 3
The user added another item which totals to 4

In the SimpleFormController.formBackingObject() method we need to figure out how many new items were added and increase the list size so the binding can occur. In our case we need to increase the list size by 1.

Popular Posts

Featured Post

Encrypting Properties File Values with Jasypt

Encrypting Properties File Values with Jasypt What's the fuzz all about? Property files are text resources in your standard web applic...