A few years ago I was using the DisplayTag library, a very nice library I must add. When doing some coding for a project I had to many records to be in the table. Therefore I used the pagination, that is the moment I ran into problems. I wanted to do the paginations via the hibernate dataaccess layer. The current DisplayTag library does not support that. There are some samples with the HEAD version, I could not get the building process with maven to work. Therefore I started to look around and found a very nice component:

http://extremecomponents.org/extremesite/welcome.jsp

This library includes a very nice view, good paginations backed by server components you can easily write yourself. Therefore I am writing this item, just to show you all how easy it is to do pagination and filtering of your objects in a nicely formatted table.

The jsp

1.  <ec:table 
2.      id="orderstable"
3.      items="orders"
4.      action="${ctx}/listOrders.html"
5.      imagePath="${ctx}/images/table/*.gif"
6.      title=""
7.      width="100%"
8.      var="order"
9.      retrieveRowsCallback="org.extremecomponents.table.callback.LimitCallback"
10.    filterRowsCallback="org.extremecomponents.table.callback.LimitCallback"
11.    sortRowsCallback="org.extremecomponents.table.callback.LimitCallback"
12.    showPagination="true"
13. >
14.    <ec:row 
15.        highlightRow="true" 
16.        onclick="javascript:document.location.href='${ctx}/editOrderOverview.html?id=${pageScope.order.id}'">
17.            <ec:column property="id" title="order.id">
18.                <a  href="${ctx}/editOrderOverview.html?id=${pageScope.order.id}">
19.                    ${pageScope.order.id}
20.                </a>
21.            </ec:column>
22.            <ec:column property="status" title="order.status"  cell="nl.primatras.backoffice.web.help.StatusCellView" filterable="false" sortable="false"/>
23.            <ec:column property="orderId" title="order.orderid" filterable="false" sortable="false"/>
24.            <ec:column property="customer.lastname" title="person.lastname"/>
25.            <ec:column property="customer.address.city" title="address.city"/>
26.            <ec:column property="createdate" title="order.createdate" format="dd-MM-yyyy (HH:mm)" cell="date" filterable="false"/>
27.        </ec:row>
28.    </ec:table>

Actually, I think this is a lot of code, so let’s step through it. Lines 9-11 take care of using an external pagination, filtering and sorting. The LimitCallback is used for that purpose. Line 8 shows you the name that can be used as the current item. Have a look at line 19, here you can see we use the order property to obtain the current value for the field order.id. Other interesting stuff, you can switch off filtering and sorting for each column, you can easily format a date field, and you can create your own cell formatters as well. Line 22 shows you how to define them in the jsp. We will show you the code for the formatter as well. But first we’ll show you the spring controller that calls the appropriate service.

The spring controller

...
1. Limit limit = LimitFactory.createInstanceOfLimit(request, "ec");
2. LimitFactory.setLimitFilterAndSortAttr(limit);
3. LimitFactory.setLimitPageAndRowAttr(limit, DEFAULT_ROWS_DISPLAYED, DEFAULT_ROWS_DISPLAYED);
...

I am having problems getting this to work, the second instance of DEFAULT_ROWS_DISPLAYED should be the value from the drop down list that lets you choose the number of items to display.

...
1. if (limit.getFilterSet().isFiltered()) {
2.     Filter[] filters = limit.getFilterSet().getFilters();
3.     for (Filter filter : filters) {
4.         String property = filter.getProperty();
5.         String value = filter.getValue();
6.         BeanUtils.copyProperty(searchOrder,property,value);
7.     }
8. }
...

The Jakarta Bean-Utils package is used to set the values from the filters into the object that is send to the search service. If you enter a value in the lastname box, the searchOrder object will receive this value for lastname so that you can use it in your data access component. The next part of source code does something simular for the ordering.

...
1. QueryResultsOrder orderBy = null;
2. if (limit.getSort().getProperty() != null) {
3.     orderBy = new QueryResultsOrder();
4.     orderBy.setOrderByProperty(limit.getSort().getProperty());
5.     orderBy.setDirection(limit.getSort().getSortOrder());
6. }
...

We created a special object called QueryResultsOrder to hold the field for sorting and the direction in one object.
Now you have all the data to call your service and put back the following to items in the request.

...
request.setAttribute("orders",orders.getOrders());
request.setAttribute("totalRows",orders.getTotalNumberOrders());
...

The last part I promised is the formatting of the cell. There is a BaseCell class that you can extend. The only method you need to overwiter is the html() method. There are a lot of utility methods. This method could look like this.

StatusCellView extends BaseCell

1. public String html() {
2.     HtmlBuilder htmlBuilder = new HtmlBuilder();
3.     Object value = column.getValue();
4.     String spanClass = getSpanClass(value);
5.     htmlBuilder.append(startTD());
6.     htmlBuilder.span().styleClass(spanClass).close();
7.     htmlBuilder.append(value.toString());
8.     htmlBuilder.spanEnd();
9.     htmlBuilder.append(endTD());
10.   return htmlBuilder.toString();
11.}

The HtmlBuilder object is used to append all html elements to. Line 4 obtains the style sheet class for the span element to create. Line 6 adds the span element and sets the style attribute class. The span element is also closed in line 6, this way the next text is added after the opening span element. This is done in line 7, and in line 8 the closing span element is added. Actually that is all there is to it. Sounds fun doesn’t it?

Hope this helps some of you to get a quick start into the eXtremeComponents

ExtremeComponents: a nice taglibrary