Query Domino data with Domino JNA (part 3): REST API and infinite scroll

With the demos from part 1 and part 2 we now have a list running in XPages that has sorting, paging and filtering. But what if you want to use Domino JNA in a REST API? To serve a JavaScript/ Angular/ React/ Vue application or, why not, an app running in Office 365?

The good news is that we already have most of the code for that. So we can take the code from demo 6, do a little refactoring, write a class for the REST API, and we’re done! In this post I’ll show you how to create the JNA-powered REST API and use it in a JavaScript grid component (for Domino people: a ‘view’) called AG Grid. Want to see the demo first?

REST API in Domino

The main reason why we need to refactor the controller class from demo 6. is that REST APIs are stateless, so we need to get rid of all Java class variables. We end up with one (public static) getEntries() method and add parameters to set the start index, number of entries to return, sort order and filter.

Creating a REST API in Domino can be done in multiple ways:

For the purpose of this demo, and to keep things simple, I’ve used the ExtLib REST control. In short: you  create an XPage (e.g. api.xsp), add the ExtLib control, set the path (the part in the URL after the XPage name, e.g. ‘contacts’), configure it as a custom REST service and point it to a Java class (eu.linqed.api.ContactsService). In that class you extend com.ibm.xsp.extlib.component.rest.CustomServiceBean and implement the doService() method to handle the request. See the demo database for an example. With that in place, we now have a working REST API serving the contacts data. The data can be sorted, paged and filtered by combining URL parameters (start, count, sortCol, sortAsc and filter).

Using the REST API in an app

For this post I created a small JavaScript demo app that uses ag-grid to show the contacts. ag-grid is a very feature-rich, open source component to build grids (sorry if that sounded like marketing – I’m not affiliated in any way with them). It comes with built-in support for sorting, filtering and infinite scrolling using a virtual row model. Plus it has versions for all the major JavaScript frameworks. Since I’m the most comfortable writing Angular I used that one.

After following the getting started tutorial I ended up with a working grid, linked to their sample data. We’re now ready to change that and link it to the Domino JNA-driven REST API we just created. The documentation describes what events we can use.

Most changes need to be made in the app.component.ts file: the component definition and configuration for the grid. We’ll first change the endpoint and immediately run into an error: the Angular app is running on a different server, so the browser shows a CORS security warning. You can fix that by (1) adding an Access-Control-Allow-Origin header to your servers’ response or (2) simply run the Angular on your Domino server. When you’re running Domino behind a proxy you can add it to the proxy configuration. Or you (normally) would create rule for your website document in names.nsf. Unfortunately those rules don’t seem to be added when you’re using an ExtLib REST Control, so you either need to use a proxy (=recommended) or add the header to the ContactsService class.

We then have the change the column definition to display properties from the contacts received from the REST API in the ‘columnDefs’ property of AG Grid (lines 25-30).

Infinite scrolling on the grid is enabled by setting the ‘infinite’ row model, according to this guide. The datasource can be found in rows 102-156. The basic idea is that when the user (almost) scrolled to the end of the list, it sends a request to the REST API to load more data. With that request it includes the current ‘state’ of the grid (sort column, filtering). You can see the request being made on line 135. Note that I’m connecting to the endpoint configured in the ‘environments’ configuration file.

Last thing is to handle a user entering something in the search field or sorting the grid. We change the ‘state’ object of the grid in the appropriate events (onGridSortChanged, onGridFilterChanged) and the grid takes care of the rest!

Have fun with the demo and don’t forget the explore the source code of the demo database and Angular demo app.