Ajax programming with Struts 2

Five steps to dynamic tables using Struts 2, Dojo and JSON

1 2 3 4 5 Page 2
Page 2 of 5

Creating dynamic tables

Ajax support in Struts 2
Struts 2 combines the best open source frameworks available to ease Ajax development. To control webflow on the server side it utilizes OpenSymphony WebWork/XWork. For dependency injection without the configuration headache it uses Guice. On the client side it utilizes Dojo, the JavaScript toolkit. Struts 2 also supports JSON, a subset of JavaScript whose abbreviated syntax makes it better suited to data interchange than XML.

A typical Ajax table -- that is, one whose data is dynamically filtered, sorted and paginated -- must receive two pieces of information from the server for every instance of data display: records comprising the single current page of data, and pagination data. The records are taken from the sorted and filtered whole data set. The paging information consists of the current page number and total number of records in the data set after filtering. Let's call the first one getRows and the second one getRowCount.

Passing contextual data

Both getRows and getRowCount require contextual information, such as what page number is being requested, what column to sort by and how to filter the requested records. The total number of records doesn't depend on sorting and pagination, so getRowCount only needs to know the filtering criteria. A Map is a simple but sufficient container for this information. Map keys are field names and Map values are criteria field values. getRows additionally needs to know which page number to display and how to sort the data. The Java bean in Listing 1 holds contextual information to be transported from and to getRows and getRowCount.

Listing 1. Java bean to transport pagination, sorting, and filtering data

public class SortedPagedFilter {
private byte direction; // direction of sorting
private String field; // field to sort by
private Map criteria; // filtering criteria
private int page; // current page
// accessors omitted

Retrieving contextual data

Most of your effort will be spent on coding the logic to return contextual information from the database. You probably are aware of the various techniques for getting a paged record set from a database. If you're using the Java Persistence API (via a JPA persistence provider like Hibernate 3) you can instruct its Query interface to return a page using setMaxResults and setFirstResult. Your JPA implementation should support a JDBC driver capable of handling your database capabilities. It should also be advanced enough to know how to issue an SQL query that will actually return the exact number of records for a given page. In this case your work is done. Unfortunately, in some cases setMaxResults and setFirstResult will only mimic the expected behavior. These calls will actually transport the entire recordset from the database, cutting off redundant records at the JVM.

For applications with many database records, there is a good chance you will need to write an SQL query native to your application database. If you are using ORM (object-relational mapping) you will have to retrieve a list of native object IDs, which you will later use in your ORM-specific query to retrieve the list of entities. For JPA it will look something like:

select o from Order where o.id in (3,6,21,30)

If you are not using ORM, POJO beans will be populated using the same approach manually.

Once you've retrieved the actual page data from the server (getRows) getting the pagination data isn't a big deal: a simple SQL query is enough to retrieve a count of rows with a filter applied.

1 2 3 4 5 Page 2
Page 2 of 5
How to choose a low-code development platform