I had a project requirement for a displaying a user workbench .This workbench would consist multiple data grids .In each grid the user will be able to see a large number of data.
These data grids should allow the user to
2. Export the data to Excel, CSV as well as PDF format
3. User customizable Pagination
5. All the grid activities (i.e. 1, 2, 3 and 4) should be Ajax enabled.
My project was a J2EE project using Struts 1.3.8 as the web framework. Struts itself does not have a direct support for such features. I used Jmesa. It is an open source Dynamic HTML Table Rendering API
that allows to filter, sort, paginate, export and inline editing of data (if required). I have configured this API according to my project needs.
The requirements that I have mentioned above (i.e. 1 to 5) are not solved by any single library or API apart from Jmesa. I have gone through the following solutions below, but none of them have the support for all mentioned features like Jmesa has.
I used JMesa extensively in my recent project. I am benefited heavily from this API . So I want to give something back to this wonderful API by contributing some code/tips/techniques related to the usage of JMesa. Complete source code is attached at the end of theis article.
Following are few topics on which I going to focus on.
1. Complete example of using Jmesa with Struts (Specifically the Ajax enabled version).
2. Practical example /recipe on the row rendering ( i.e. proper usage of HtmlRowRendererImpl )
3. Proper usage of ColumnSort with examples .
4. I have a generic comparator (I am working on this currently ), which deals with some real life data type problems in terms of sorting (for example a String containing a date or number, so the sorting becomes weird). This comparator is capable enough to handle such frequently required real life problem scenarios.
1. Complete example of using Jmesa with Struts
(With Ajax )
Brief Summary of what I want to do:
First, setup an application configuration so that Struts 1.x and Jmesa works together. Then I will have an action class JmesaDispatchAction.java (I am using DispatchAction here so that if wants same action to works for multiple jmesa table less struts mapping and code is required ) which will have a method load(). This load() method is everything .
Create the structure for any standard struts project. Noww place Jmesalibrariess in side WEB-INF/lib folder. Place jmesa.properties inside WEB-INF. Inside web.xml create its entry like the following:
Place Jmesa related css,js and image files inside css,js and images folders respectively, all these folders are under WebContent. Please see the set up image below:
Code the Action class and the JSP:
2. Row Rendering Recipe
Suppose I want to highlight a particular row with a specific color for a specific value... How would I do that?
This is an ideal case for using a Custom HtmlRowRenderer which will extend HtmlRowRendererImpl.
Now we need to override the default public Object render(Object item, int rowcount) method to our specific requirement.
In this case the data list contains a DTO object which has a boolean field named ok. If this field value is true we need to highlight the row with green color.
Here is the code for that
public class CustomHtmlRowRenderer extends HtmlRowRendererImpl
public Object render(Object item, int rowcount)
HtmlBuilder html = new HtmlBuilder();
html.id(getCoreContext().getLimit().getId() + "_row" + rowcount);
//Get the actual value of ok field
Object okValueObj = ItemUtils.getItemValue(item, "ok");
String valueStr = String.valueOf(okValueObj).toLowerCase();
Now we need to inform the Tablefacade object about this renederer .Inside getHtml we do this by the following lines of code
* Override and customize the sorting of the table facade
ColumnSort customColumnSort = new CustomColumnSort();
Before row rendering customization, the grid was like :
After row rendering customization, the grid is like :
3. Custom Sorting Recipe
How to sort a table according to my own choice using Jmesa?
Jmesa comes with its own nice way of sorting. But for custom sorting of your own you need to write your own Custom Sorting class which will implement ColumnSort interface and implement the sortItems method of the said interface to customize the sorting.
Remember sortItems() method is the place where you whatever customization. The code is written below to sort the data on two properties age and displaydate.
public class CustomColumnSort implements ColumnSort
public Collection<?> sortItems(Collection<?> items, Limit limit)
ComparatorChain chain = new ComparatorChain();
SortSet sortSet = limit.getSortSet();
Iterator sortItr= sortSet.getSorts().iterator();
Sort sort =(Sort)sortItr.next();
GenericComparator genericComparator = null;
if (sort.getOrder() == Order.ASC)
genericComparator= new GenericComparator(sort.getProperty(),true,GenericComparator.NUMERIC_STRING);
genericComparator= new GenericComparator(sort.getProperty(),true,GenericComparator.DATE_STRING);
else if (sort.getOrder() == Order.DESC)
* For descending sort one extra parameter sorting mode (value false)
* is passed to the GenericComparator.
* By default its value is true.
genericComparator= new GenericComparator(sort.getProperty(),true,GenericComparator.NUMERIC_STRING,false);
genericComparator= new GenericComparator(sort.getProperty(),true,GenericComparator.DATE_STRING,false);
* This is the main place where the Generic comparator is added to the
* ComparatorChain for sorting
if (chain.size() > 0)
Collection((List<?>) items, chain);
Now we need to inform the HtmlTable object about this custom sort object .Inside getHtml we do this by the following lines of code:
HtmlTable table = (HtmlTable) tableFacade.getTable();
HtmlRow row = table.getRow();
* Override and customize the rendering of the table facade
CustomHtmlRowRenderer customHtmlRowRenderer = new CustomHtmlRowRenderer();
4. Handle real life sorting issues with GenericComparator
I want to write one and only comparator which will handle all types of sorting.
Even if you have that there are some situations where the comparator will fail. For e.g. you have some DTO objects within a list which you want to sort. Now the DTO has a displaydate field which is of type String but displays a Date.
Now when the sorting takes place the comparator will try to sort it as a String but the user will be expecting a sort on date !
I mention these particular field types as hybrid data type. We can say displaydate had a Date String hybrid datatype. Similarly, we may face problems with Numeric String, Boolean String etc etc.
Here comes my brain child custom Generic Comparator. Just inform the comparator about the hybrid data type and let it do its sorting job.
Inside sorItems method of CustomColumnSort I have used generic comparator .
For proper java data type you just need to create the comparator like
GenericComparator comparator= new GenericComparator(<String fieldNameToBeSorted>)
For hybrid java data type you need to create the comparator like
public GenericComparator(<String fieldNameToBeSorted>,<boolean hybridDataType>,<String hybridDataTypeName>)
Inside CustomColumnSort I have shown how to deal with hybrid data type like the following
GenericComparator genericComparator= new GenericComparator(sort.getProperty(),true,GenericComparator.NUMERIC_STRING);
If it was a normal data type the code would have been like:
GenericComparator genericComparator= new GenericComparator(sort.getProperty());
I've attached the complete example source code in the form of a war file. Please have a look. In case you need any reference you may go to the URL:
and have a look. I have written an article about Jmesa usage with Struts over there and my sample code is also uploaded there.