Spring Roo’s GWT front end has a listing view that uses CellTable to display the data. CellTable has sorting capability however Roo doesn’t yet utilise this feature, possibly waiting until sorted finders are implemented. To enable this feature we just have to roll up our sleeves and get our hands dirty.
Step 1: Enabling sortable columns
The first step is to enable the columns we want to become sortable. This is achieved in the entity’s view, just after init() is called. Presuming our entity is called Person, the view’s constructor would look like this:
Step 2: Setup data provider
The next step is to create a data provider and connect it to the table. AbstractProxyListActivity already has an onRangeChanged() method, perfect for use with AsyncDataProvider, so let AbstractProxyListActivity extend AsyncDataProvider:
The data provider needs to connect to a display that implements HasData, so we need to do this from the presenter. GWT MVP works by attaching and detaching views from their presenters when the views are finished with, so the data provider needs to do the same. Conveniently, Roo’s view interfaces have defined a method asHasData() to retrieve the table. From within start() and onStop() we need to handle the connection to the display:
Step 3: Redefine field name map
The magic happens in the onRangedChanged() method of the data provider. It’s here where we can interrogate the table to check the sort order and return the row data nicely sorted. But before we do that, we need a way to map the columns to field names. Roo generates a Set of field names however it uses HashSet so the order in which the table columns are generated is lost. This needs to be overridden in the view’s subclass before init() to use an order-preserving implementation:
Step 4: Implement range change callback
So now in onRangeChanged() we can map columns to field names and create an order by clause (or something similar):
From here a regular range request would be called as follows:
- Make a server request using findPersonEntries()
This call chain may be overloaded to accept the orderBy string. The overloaded fireRangeRequest() would then be called provided that orderBy is not empty.
Step 5: Create a sorted finder
The last couple of things to do are to create a sorted request that accepts the order by string and then wire the client up through RequestFactory. Roo does not yet support sorting in dynamic finders so that’s left up to us to implement. You can check Roo’s generated finders in the AspectJ files for an example on how to create a finder. Note that overloading is not supported in RequestFactory as of 2.2.0 so a unique name must be chosen:
Step 6: Wire up RequestFactory
Because the *Request interfaces are owned by Roo, we must extend them to customise the request. The following steps will need to take place, continuing with the Person example:
- Extend the interface PersonRequest, adding the new finder method findPersonEntriesSorted();
- Extend the interface ApplicationRequestFactory to add the new Person request interface from the previous step;
- Update ApplicationMasterActivities to use the new extended ApplicationRequestFactory interface;
- Bind the new request factory interface in the Gin module, ScaffoldModule.
You should now be able to sort your columns in the entity’s list view.