Create an Action
, as shown in Example 4-8, that uses the
BeanComparator
class of the Jakarta Commons
BeanUtils library to sort the underlying Collection.
Example 4-8. Sorting tabular data with an Action
package com.oreilly.strutsckbk.ch04; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.BeanComparator; import org.apache.commons.collections.comparators.ReverseComparator; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class ViewForecastAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // create the weather bean WeeklyWeather weather = new WeeklyWeather( ); // create a list to hold the forecast List list = new ArrayList( ); list.addAll( weather.getWeekForecast( ) ); // get the sort by request param String sortBy = request.getParameter("sortBy"); // get the reverse request param boolean reverse = false; String reverseParam = request.getParameter("reverse"); if (reverseParam != null) reverse = Boolean.valueOf(reverseParam).booleanValue( ); // sort the list if (sortBy != null) { Comparator comparator = new BeanComparator(sortBy); if(reverse) comparator = new ReverseComparator(comparator); Collections.sort( list, comparator ); } // add the list as a request attribute and forward to the JSP request.setAttribute( "weekForecast", list ); return mapping.findForward("success"); } }
Then create an action
element in the
struts-config.xml that uses
ViewForecastAction
and forwards to the JSP page
that displays the table:
<action path="/ViewForecast" type="com.oreilly.strutsckbk.ch04.ViewForecastAction"> <forward name="success" path="/sorted_struts_table.jsp"/> </action>
On the JSP page (sorted_struts_table.jsp), shown
in Example 4-9, the table header cells contain links
to the ViewForecast
action. Each link sets request
parameters that indicate the property name to sort by and if the sort
order is reversed (i.e., descending).
Example 4-9. Using table column headers for sorting
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix= "bean" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix= "logic" %> <html> <head> <title>Struts Cookbook - Chapter 4 : Sorted Struts Table</title> </head> <body> <table width="60%" border="2"> <tr> <th>Day of Week<br /> <a href="ViewForecast.do">unsort</a> </th> <th>Chance of Precipitation<br /> <a href="ViewForecast.do?sortBy=chancePrecip">asc</a> <a href="ViewForecast.do?sortBy=chancePrecip&reverse=true">desc</a> </th> <th>Expected Precipitation (inches)<br /> <a href="ViewForecast.do?sortBy=rainfall">asc</a> <a href="ViewForecast.do?sortBy=rainfall&reverse=true">desc</a> </th> </tr> <logic:iterate id="forecast" name="weekForecast"> <tr> <td> <bean:write name="forecast" property="day"/> </td> <td> <bean:write name="forecast" property="chancePrecip"/> </td> <td> <bean:write name="forecast" property="rainfall"/> </td> </tr> </logic:iterate> </table> </body> </html>
The approach shown in the solution performs an in-memory sort of the data displayed in an HTML table.
Tip
If the tabular data were stored in a database, you would need to store the data collection in the session or refetch the data from the database between requests.
The table is sorted by creating a
java.util.Comparator
based on the name of the
property to sort by. The BeanComparator
class
provides the intelligence to create the comparator using JavaBean
introspection. The created Comparator
sorts the
data based on the natural ordering of the property. If a reverse or
descending order sort is desired, a
ReverseComparator
is created from the
BeanComparator
.
The Solution for this problem is easy. The grunt work of creating the
Comparator
s is handled by the
BeanComparator
. If you add a new property to the
object in the collection, it can be sorted by passing in a request
parameter with the name of that property. If you want to return the
collection to its natural, unsorted state, don't
pass in the sortBy
parameter.
Sorting in ascending or descending order is handled via the
reverse
request parameter. This parameter is
mapped to a Boolean variable. If reverse
is true,
a ReverseComparator
is used.
The JSP page adds sorting capability by providing links that forward
to the ViewForecast
action. Each link specifies a
sortBy
parameter corresponding to the column to be
sorted. The link for sorting in descending order adds the
reverse
parameter. Figure 4-5
shows the resultant web page for the Solution. Here the
"desc" link in the third column was
clicked to order the data by greatest expected rainfall. You can see
the generated URL for the "desc"
link in the browser's status bar.
This Solution was based in-part on suggestions made in the struts-user mailing list. One useful thread posting by Henri Yandell is archived at http://www.mail-archive.com/struts-user%40jakarta.apache.org/msg95356.html.
JSTL tags can be used to create the table instead of the Struts
logic:iterate
and bean:write
tags. Recipe 4.3 shows
examples of JSTL to create tables. Recipe 4.6 shows you how to provide table sorting using
the display tags open source tag library. You do
not need to code any special Java sorting actions if you use this
popular tag library.
For further information on the BeanUtils sorting capabilities, check out the JavaDocs at http://jakarta.apache.org/commons/beanutils/api/org/apache/commons/beanutils/BeanComparator.html.
Get Jakarta Struts Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.