Multi-page Lists and Page Traversal frameworks


As seen in the last section, < logic:iterate > can be used in conjunction with indexed html tags to display and edit list forms. However read-only tabular displays are more common than editable list forms in enterprise applications. Such read-only tables span multiple pages with data ranging from ten rows to thousands. The IterateTag can also be used for displaying read-only data by iterating over a collection and rendering the data using < bean:write >. For multi-page lists, the attributes offset and length are useful. The offset indicates the index from where to start the iteration in the page relative to the first element (index = 0). The length indicates the maximum number of entries from the collection to be displayed in the page. Using these two attributes it is possible to build a multi-page list.

But the task is more daunting than you can imagine. Believe us. Multi-page list display will not be your only worry. You will be asked to provide a browsing mechanism ‚ previous, next , first and last to traverse the collection. You will have to sort the data for the chosen column (and still do a previous, next etc.). You will be asked to group the data, aggregate and sum columns and format them. In addition you will have to make it easier to the page author to apply different display styles to the list. Before you know it, the seemingly trivial task has turned into a Frankenstein!

The plain vanilla IterateTag simply cannot be stretched too far. A robust framework exclusively to perform the above tasks is needed. Fortunately such frameworks are available at no charge. Why reinvent the wheel unless you have a unique and stringent requirement not satisfied by one of these frameworks? Three such frameworks are reviewed below. One is free, the other two are open source Let us examine what is available and what is missing in these frameworks and how they fit into the Struts way of building applications. The three frameworks are:

  1. Pager Taglib (http://jsptags.com/tags/navigation/pager/)

  2. displayTag (http://displaytag. sourceforge .net/)

  3. HtmlTable (http://sourceforge.net/projects/htmltable/)

Pager Taglib

Pager Taglib covers the display aspects of list traversal very well. Provide it the minimal information such as rows per page and URL and it will control the entire paging logic. You are in complete control of the iterating logic and table display. (If using the IterateTag, offset and length attributes are not needed). Hence you can completely customize the look and feel of the table using CSS. The Pager taglib does not provide any assistance for the table display. Neither does it handle editable list forms, sorting or grouping. If all you need is an easy and elegant way to traverse list data, you should definitely consider using the Pager taglib and you will be glad you did. Below we cover a short note on how to use the Pager Taglib with Struts.

Start with an Action that creates the collection to iterate and put it in HttpSession using results as the key name . Then forward to the JSP that uses the Pager taglib. This JSP is shown in Listing 6.11. The resulting HTML is shown in Figure 6.2. The pg:pager tag has two important attributes ‚ url and maxPageItems . They specify the destination URL when any of the navigation links are clicked and the number of items per page respectively. In Listing 6.11, the url is traverse.do ‚ a simple ForwardAction that forwards to the same JSP. The JSP uses the iterate tag to iterate the collection. Th pg:item defines each displayable row. The pg:index , pg:prev , pg:pages and pg:next together display the page numbers , previous and next links. These tags even provide you the flexibility of using your own images instead of plain old hyperlinks . Using pg:param (not shown in the listing), additional request parameters can also be submitted with the url.

Listing 6.11: Using Pager taglib with Struts
 <pg:pager url="traverse.do" maxIndexPages="10"                                    maxPageItems="5">  <TABLE width="100%">   <TR>    <TD align="center">     <TABLE width="80%" border="1">      <TR>       <TH width="20%">Name</TH>       <TH width="20%">Address</TH>       <TH width="20%">City</TH>      </TR>      <logic:iterate id="row" name="results" scope="session"                               type="mybank.app1.CustomerData">       <pg:item>        <TR>         <TD><bean:write name="row" property="name"/></TD>         <TD><bean:write name="row" property="address"/></TD>         <TD><bean:write name="row" property="city"/></TD>        </TR>       </pg:item>      </logic:iterate>     </TABLE>     <TABLE width="80%" border="0">      <TR><TD>&nbsp;</TD></TR>      <TR align="center">       <TD>        <pg:index>         <pg:prev><a href="<%=pageUrl%>">[<< Prev]</a></pg:prev>         <pg:pages>           <a href="<%= pageUrl %>"><%= pageNumber %></a>         </pg:pages>         <pg:next><a href="<%= pageUrl%>">[Next >>]</a></pg:next>        </pg:index>       </TD>      </TR>     </TABLE>    </TD>   </TR>  </TABLE> </pg:pager> 
 

Figure 6.2: Traversing the multi page list using Pager Taglib from jsptags.com

DisplayTag and HtmlTable frameworks

The pager taglib does paging through a table and nothing more. If sorting and grouping are one of your requirements, you can use one of DisplayTag or HtmlTable frameworks. Each of them has their own paging logic and should not be used in conjunction with the Pager Taglib. Covering these frameworks is beyond the scope of this book. Please check their respective web sites for documentation and user guide. Table 6.3 provides a comprehensive feature comparison between the two. DisplayTag shines in many categories but lacks the table based editing features. DisplayTag is not tied to Struts in any way. Neither does it enforce MVC. HtmlTable on the other hand mandates strict adherence to MVC. All the pagination, sort requests are handled by a pre-defined Action class (ServeTableAction) provided with the library. Further customization is needed to chain it to your own business processing before/after ServeTableAction does its job.

Table 6.3: Feature Comparison between DisplayTag and HtmlTable

Feature

DisplayTag

HtmlTable

Display Formatting

Very rich and customizable using CSS.

Limited features. Formatting is based on a back end XML file and hence not directly under page author ‚ s control.

Column Grouping

Yes

Yes

Nested Tables

Yes

No

Coding Style

The display model should be created in advance, but the formatting can be invoked from the JSP using hooks called decorators

Does not require controller (such as Struts or its Action). The JSP itself can control the paging.

The display model and its formatting should be performed in advance (in a Action). The paging is tied to Struts. Needs a predefined Action called ServeTableAction. Strictly MVC based.

Paging

Customizable auto paging

Fixed style auto paging

Sorting

Yes

Yes

I18N

No. Messages can be externalized to a properties file but cannot be localized as of 1.0b2. Full support is expected soon.

Yes. Can use Struts resource bundle

Editable column

No

Yes, but form is submitted to a predefined Action. Action chaining for custom processing can be setup with minor customization.

Documentation and examples

Good

Limited

User community

Relatively high

Less

Creating the Model for iteration

In the last two sections, you looked at three options for traversing and displaying the collection. For limited amount of data, creating the collection is a no-brainer. The size of the result set is managable and you can tolerate the database returning it at one shot. As the collection gets larger, it consumes a significant amount of memory and absolutely does not make sense to waste the precious runtime resources. Instead of maintaining the entire collection in memory, you can use the Value List Handler pattern (Core J2EE Patterns). Figure 6.3 shows the class diagram for Value List Handler.


Figure 6.3: Value List Handler pattern

ValueListHandler can be thought of as a fa ƒ §ade for the underlying collection. ValueList - the data object collection is traversed using the ValueListIterator . The Data Access Object encapsulates the logic to access the database in the specified format ‚ read-only EJB, direct JDBC or O/R mapper, the latter two approaches being preferred. We recommend designing the Value List Handler intelligently so that it fetches data in bulk using read-ahead (a.k.a pre-fetch ) mechanism ‚ i.e. data to serve two to three pages is retrieved and in advance if needed so that the delay in retrieval is minimized. The beauty of this pattern is that you can expose the ValueListIterator to the IterateTag and the tag will believe that it is traversing the original Iterator, while you can intelligently serve the requested rows and keep fetching in the background.

In this context it is advantageous to combine an O/R mapping framework that allows you use SQLs to search the database. Most of the O/R mapping frameworks provide caching mechanisms. Hence the overhead of object creation after retrieval is eliminated since the object in already in the cache. Moreover you can take advantage of the features provided in the RDBMS. For instance, DB2 provides a feature called ROW_NEXT.

Suppose that the requirement is to display 10 rows per page. Here is strategy for devising a responsive system while working with large data set. When the query is first made, data for three pages (30 rows) is prefetched and maintained in the HttpSession. When the user requests the third page, the ValueListHandler realizes that the end of the cache is reached. It goes ahead and serves the third page (21-30 rows). After that it initiates an asynchronous request to fetch another 30 rows from the database (This will need a scheduling mechanism to which individual valueListHandlers submit their pre-fetch requests). When the next 30 rows are retrieved, it caches them along with the original 30 rows. Hence a cache of 60 rows is maintained per user. (This is to prevent a ‚“cache-fault ‚½ if the user decides to go to previous page while on third page). Depdending on the size of the displayed objects, you have to choose an optimal cache within the Value List Handler. If the objects are 1K each, 60 objects means 60K of memory consumed by the corresponding HttpSession. This is absolutely not recommended. A rule of thumb is that HttpSession size should not exceed 20K per user. [Another reason to make the display objects only as big as needed and no bigger. Overcome the tendency to reuse bloated value objects and data transfer objects from elsewhere.]

Coming back to the database features for large result sets. The following SQL can be used to fetch the first 30 rows:

 SELECT FIRST_NAME, LAST_NAME, ADDRESS   FROM CUSTOMER,   WHERE    ORDER BY FIRST_NAME FETCH FIRST 30 ROWS ONLY  OPTIMIZED FOR READ ONLY 

When the user reaches the third page, the ValueListHandler makes a prefetch request for the next 30 rows (Rows 31 to 60). The following SQL can be used to fetch them:

 SELECT * FROM  (SELECT FIRST_NAME, LAST_NAME, ADDRESS     FROM CUSTOMER,     WHERE      ORDER BY FIRST_NAME) AS CUST_TEMP WHERE   ROW_NEXT BETWEEN 31 AND 60    OPTIMIZED FOR READ ONLY 

This SQL consists of two parts . The inner SQL is exactly the same as the SQL issued earlier and can be thought to be fetching the data into a temporary table. The ROW_NEXT in the outer SQL identifies the exact rows to be returned from the retrieved result set. The values 31 and 60 can be substituted dynamically. The proprietary SQL no doubt impacts the portability, but almost every database used in the enterprise today has this feature. The Java code still is portable.




Struts Survival Guide. Basics to Best Practices
Struts Survival Guide: Basics to Best Practices (J2ee Survival Series)
ISBN: 0974848808
EAN: 2147483647
Year: 2004
Pages: 96

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net