Data Binding to Multiple Records in Spring (with Velocity)
Submitted by Aaron Longwell on Mon, 2005-06-13 14:54.A client came to me recently asking for modifications to their web application. The application has a many to one relationship; we'll call it the "one" side a Studio, and the "many" side's elements "Films". Updated information for films (box office numbers, tickets sold, etc) comes in batches. Searching, selecting and editing Films one at a time is inefficient, so the client requested batch editing ability.
We started from the user's perspective and decided a spreadsheet-style interface would be most efficient. Users will perform a search to get a list of Films, then edit them in the spreadsheet interface. This required data binding to multiple database records simultaneously.
Here's how I did it in Spring with a Velocity view.
For the most part, the data binding process works the same with multiple records as it does with one. I extended the SimpleFormController, with an implementation that retrieves a List of Films from the data layer in its formBackingObject() method.
That was working fine, so I began to code up the edit form. Here's an excerpt of the first (broken) attempt:
#foreach($film in $command)
#set($index = $velocityCount - 1)
#springBind("command[$index].boxOffice")
#end
That attempt did not work (received an error saying the object command[0] does not exist as an attribute). I scoured the forums and documentation and found no help. Everything seems to check out. I eventually had to look at the Spring source to find out why my code was not working. As it turns out, Spring's data binding assumes that the command object is a simple object (not a List, Map or other Collection). The special List and Map syntax:
#springBind("command.map['key']")
#springBind("command.list[index]")
does not apply the command object itself. Knowing that, I changed my formBackingObject() method to return a command object (call it FilmBatch) that wraps a List of Film objects. I then changed the Velocity template to the following:
#foreach($film in $command.filmList)
#set ($index = $velocityCount - 1)
#springBind("command.filmList[$index].boxOffice")
#end
