I recently came across a blog post describing how *not* to use the Spring Web MVC form tag library. Spring Web MVC is one of those things that has a high learning curve but it pays off big once you get the hang of it. The form tag library is no exception. The original blog poster seems to want to display a list of things the form user can manipulate and then send the changes back to the app server. There are a few different ways we can do this with Spring Web MVC and some JSTL libraries so let’s take a look at the way I prefer to do it.
Spring Web MVC utilizes the ModelAndView class to encapsulate the M and V of MVC. The model part is simply a map of objects associated with a request. The key is the string name that you will use to access the object via the tag libraries. Placing an object with a key of “userPrefs” into the map will make the UserPrefs object available to the HttpServletRequest and eventually part of the implicit request object that is part of JSPs. In order to display any user data in a JSP it has to be part of the request object and it gets there by placing it in the Map used by ModelAndView.
In my experience with Spring Web MVC I’ve found that most form controller classes extend SimpleFormController. SimpleFormController derives most of its lifecycle from AbstractFormController, which provides us with a few interesting methods. There is one method in particular that is interesting. The referenceData(HttpServletRequest request) method returns a Map and this method is called during the showForm(…) method. showForm returns a ModelAndView object which will include whatever data is included in the Map returned by referenceData. The default implementation of referenceData returns null, so we have to override it in our class that extends SimpleFormController.
Here is some example code from my controller class which extends SimpleFormController. The point here is to provide a list of Bookmark objects to the form for a user to delete.
@Override
protected Map referenceData(HttpServletRequest request) throws Exception {
List userBookmarkList = bookmarkService.getUserBookmarks(
request.getUserPrincipal().toString());
Map model = new HashMap();
model.put(“userBookmarks”, userBookmarkList);
return model;
}
This is pretty simple example. It’s first getting the user from the request object. This is an authenticated session where a user has provided a login name and password. That name is retrieved from the request object and used to get a List of all of their bookmarks. The List is then put into a HashMap with the key “userBookmarks”.
After referenceData returns the Map those entries are then passed on to the view by the showForm method. We can use a couple JSTL tag libraries to iterate over the list and display each bookmark while building the form. The following is an excerpt from the view (NOTE – This is pre-Spring 2.5):
<%@ taglib prefix=“form” uri=“http://www.springframework.org/tags/form” %> <c:forEach items=“${userBookmarks}” var=“bookmark”> <form:checkbox path=“bookmarkIds” value=“${bookmark.id}”/><c:out value=“${bookmark.id}”/> — <c:out value=“${bookmark.title}” escapeXml=“true”/><br/> </c:forEach> <input type=“submit” value=“Delete checked bookmarks”/> |
This view uses two tag libraries, one from JSTL, the other being the Spring form tag library. Within the form tags the JSTL forEach tag is used to iterate over the list of bookmarks. The list is obtained via the ${userBookmarks} variable. This calling convention takes advantage of the search order for finding request parameters used by JSTL. Part of the search includes looking in the request object that is part of every JSP. The items attribute is the object we want to iterate over, that being the object keyed by userBookmarks.
That object is the List of bookmarks we got from the business tier. By iterating over the bookmarks we have access to each Bookmark object and each of it’s fields. The checkbox tag is used to build up the HTML view of the each bookmark with a check box next to it for the user to click. When the user is done selecting bookmarks to delete the onSubmit method is called back in the controller.
So how does Spring know which bookmarks have been checked in the form? The form object bound to the form keeps track of the checked bookmarks. This form object is very simple, it encapsulates an array of Strings and provides a getter and setter for the array.
package net.anthonychaves.bookmarks.dataobject;
public class DeleteBookmarksForm {
private String[] bookmarkIds;
public void setBookmarkIds(String[] bookmarkIds) {
this.bookmarkIds = bookmarkIds;
}
public String[] getBookmarkIds() {
return bookmarkIds;
}
}
The “value” part of our checkbox contains the bookmark ID. When the checkbox is checked and the form is submitted the Spring dispatcher servlet collects all of the checked values of the same path into an array and puts them into the DeleteBookmarksForm object. The form object is then passed to the DeleteBookmarksController via the onSubmit method. We don’t have to implement the entire onSubmit method, though. The default implementation calls doSubmitAction which takes only our command object, in this case DeleteBookmarksForm, as an argument. Once we have a list of bookmark IDs to delete we can call the business tier to remove them from the database (after appropriate error checking, of course).
Spring 2.5 introduces the form:checkboxes tag which eliminates the need to use the JSTL forEach tag to iterate over the list of objects. The checkboxes tag takes care of that for you.
There is more to working with lists in Spring Web MVC than the material presented here. I’ve included a few references below in case you’re interested in finding out more. Thanks for reading and as usual let me know if you have any questions or comments!
2 comments ↓
we r moving to spring 2.5 .. u have any idea from where we can get some working examples for sring 2.5 web MVC , as spring 2.5 seems a lot different from previuos versions
In this how to put checked=”true” while the body onload.Can anybody please help in this?
Leave a Comment