Dynamic sorting using GenericComparator for rich:dataTable, DataModel, SeralizedDataModel, its a key part of every JSF, Richfaces powered applications in the world. If I say dynamic sorting; of-course you will have couple of thoughts or question in your mind, like this:
- Dynamic sorting – how it works?
- Which datatypes are supported in GenericComparator?
- How to integrate dynamic sorting into JSF and Richfaces component in your application?
Of-course, I will be answering all these questions in detail. However If you have any queries, please leave a comment.
Dynamic sorting – how it works?
Dynamic sorting is performed using Generic Comparator in Java. I have created simple and generic comparator class to do this key functionality of your application. Click here to know – how it works.
Datatypes supported in dynamic sorting?
Currently GenericComparator supports following data types. I’m thinking to include support for Enum type as well in next update.
- Integer
- String
- Long
- Date
- Float
- Double
Integrate dynamic sorting into JSF/Richfaces
Previously I have written an article about How to do: JSF/Richfaces/Seam lazy/dynamic data loading with pagination?. This article will give a complete idea of rich:dataTable & SerializedDataModel lazy data loading with pagination implementation. In continuation to that, I will describing below about In which part of the code, you have to put GenericComparator to get a ability of dynamic sorting.
Step 1
Health check! Purpose of this check to make you comfortable in below steps, following steps are extension or continuation of above article
- Understood DynamicDataModel class implementation
- Understood how SerializableDataModel class extended in above article
- Understood how walk() method used in the above article
Good work congrats, you’re good to go!
Step 2
Declare following two local variables in DynamicDataModel class to manipulate Sorting values
1 2 |
private String sortField = null; private boolean ascending = true; |
Step 3
Download a GenericComparator.java from GitHub repo and place it in your project
Step 4
Go to DynamicDataModel class and implement org.richfaces.model.Modifiable interface like below:
1 2 3 |
public class DynamicDataModel extends SerializableDataModel implements Modifiable { ... } |
Modifiable interface provides one override method called modify(List<FilterField> filterFields, List<SortField2> sortFields); with help of modify method, we are going to determining Key values of sortField & sortOrder (ascending or descending)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@Override public void modify(List<FilterField> filterFields, List<SortField2> sortFields) { if (null != sortFields && !sortFields.isEmpty()) { SortField2 sortField2 = sortFields.get(0); Expression expression = sortField2.getExpression(); String expressionString = expression.getExpressionString(); if (!expression.isLiteralText()) { expressionString = expressionString.replaceAll("[#|$]{1}\{.*?\.", "").replaceAll("\}", ""); } this.sortField = expressionString; if (sortField2.getOrdering() == Ordering.ASCENDING) { this.ascending = true; } else if (sortField2.getOrdering() == Ordering.DESCENDING) { this.ascending = false; } } } |
As per article we are going to use only second parameter sortFields for sorting; filterFields we will see later in next article.
Step 5
Now key portion of sorting implementation comes to walk() method, that’s why we did a health check in step 1. You can decide how you want to do implementation of sortField & ascending variable values in two possible way.
Possibility 1
After getting a List values from service/web service using getItemsByrange method you can apply sorting using GenericComparator class
1 2 3 4 5 6 7 8 |
// we can populate the data from Service Call/Web Service Call // For eg. Data from database or Search results using Range values // Define getItemsByrange() method to extract the required data // by passing the range values List sampleDataList = getItemsByrange(this.firstRow, this.numberOfRows.intValue()); // Apply Generic Comparator for sorting Collection.sort(sampleDataList, new GenericComparator(this.sortField, this.ascending)); |
Possibility 2
Passing a sortField & ascending parameter value to getItemsByrange method and process it at service/web service side
1 2 3 4 5 6 7 8 9 |
// We can populate the data from Service Call/Web Service Call // For eg. Data from database or Search results using Range values // Define getItemsByrange() method to extract the required data // by passing the range values List sampleDataList = getItemsByrange(this.firstRow, this.numberOfRows.intValue(), this.sortField, this.ascending); |
Completion view of Possibility 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException { // This is method we have to populate a data for DataTable // Range parameter provides the firstRow value and no. of rows value. // Extract those values to local variables this.firstRow = ((SequenceRange) range).getFirstRow(); this.numberOfRows = ((SequenceRange) range).getRows(); // We can populate the data from Service Call/Web Service Call // For eg. Data from database or Search results using Range values // Define getItemsByrange() method to extract the required data // by passing the range values List sampleDataList = getItemsByrange(this.firstRow, this.numberOfRows.intValue()); // Apply Generic Comparator for sorting Collection.sort(sampleDatalist, new GenericComparator(this.sortField, this.ascending)); // Now store the data to wrappedKeys and // wrappedData components for the framework to make use of. wrappedKeys = new ArrayList(); if (!sampleDataList.isEmpty()) { for (SampleData item : sampleDataList) { wrappedKeys.add(item.getId()); wrappedData.put(item.getId(), item); visitor.process(context, item.getId(), argument); } } } |
Step 6
We have completed the Java portion of sorting implementation, let’s move on to JSF/Richfaces code snippet. Add following two attributes sortable & sortBy in the rich:column tag, this important to make rich column sortable
1 |
<rich:column sortable="true" sortBy="#{item.firstName}"> |
When user clicks on First Name column on the page, walk() method receives the value which column has clicked and which sort order requested (asc or desc) throught sortField & ascending variable.
Downloads
GenericComparator.java DynamicDataModelWithSorting.java SampleData.javaCompletion
That’s all, you have successfully implemented the JSF-Richfaces dynamic Sorting with rich:dataTable!