All articles

Driving the bathing water quality API from JavaScript

Bathers on a beach, stepping into the sea.

As part of the EA project, we have developed a reference application which shows the data off fairly comprehensively. However, there’s quite a bit of code in that project, so in this blog posting I wanted to strip it down and show the basic elements of driving the bathing water API from JavaScript.

I’ll keep the project simple, and just show a few elements from the data. The demo is online here.

Data model

Bathing water sites (note: they’re not just beaches, because some of the monitoring points are inland!) are RESTful resources in the API. The resources use content negotation to decide what format to return the resource description in: the default is HTML, but it can also be XML, CSV, Turtle and, most usefully for webapps, JSON. Clicking on a link in a browser, however, doesn’t provide an opportunity to specify the content Accept: header, so the API also allows the content type to be specified by appending a suffix (.json) or by the _format parameter. Incidentally, the next few examples will work best if you have JSON viewer plugin for your browser, such as JSONview. The following two links both return a JSON description of a particular bathing water:

https://environment.data.gov.uk/doc/bathing-water/ukc2102-03600.json
https://environment.data.gov.uk/doc/bathing-water/ukc2102-03600?_format=json

whereas this link returns the collection of bathing waters:

https://environment.data.gov.uk/doc/bathing-water.json

Well, almost. There are actually over 500 sites that the EA monitors. Rather than return a large resource collection all at once, the API will split a collection into pages, and you’ll see the following in the returned data:

"itemsPerPage" : 10, 
"next" : "https://environment.data.gov.uk/doc/bathing-water.json?_page=1", 
"page" : 0, 
"startIndex" : 1, 
"type" : "https://purl.org/linked-data/api/vocab#Page"

Each bathing water is described as a JSON object structure with keys denoting a particular property (e.g. eubwidNotation, tr: “EU bathing water id notation”), and values denoting the value of that property (e.g. “ukc2102-03600”). The object keys are derived from the RDF properties in the underlying linked-data model, but simplified from URI’s to short names to be more in keeping with idiomatic JSON. You may not the special property _about: this is the actual data URI for that value, and following that link will return a resource description as we discussed above.

A reasonable question is: what gets returned in the object description? The underlying RDF objects can have many properties, and are connected in to a rich graph of related objects. In different circumstances, we might want more or less of this graph to come along when we fetch an object description. The Linked Data API describes this as selecting the view. A view is a configuration of the API to determine which properties get returned. Views are named, and there’s always a default view. We can select the view we want with a _view parameter to the REST call. Here, the basic view returns just the name and type of the resource:

https://environment.data.gov.uk/doc/bathing-water/ukc2102-03600?_format=json&_view=basic

View definition is the responsibility of the API configuration writer, not the developer calling the API. Suppose a developer wants a slightly different set of properties than the API configuration author provided. What then? Fortunately, there is a way for the API caller to fine-tune the view, by specifying property paths that should be included in the view. Suppose we want to add just the bathing water image to the basic view. From the documentation, or by just exploring the returned results in a browser, we can see that the latestProfile of a bathing water gets to the profile resource, and the profile has a webResImage property. So by adding that property path to the REST resource URL, we get the augmented view we want:

https://environment.data.gov.uk/doc/bathing-water/ukc2102-03600?_format=json&_view=basic&_properties=latestProfile.webResImage

With those elements in place, we can look at driving the API from JavaScript.

Invoking the API from a web page

It’s quite straightforward to call a JSON API from JavaScript, using jQuery’s $.ajax function. There are, however, a couple of nuances to take into account. The first is the API is not on the same host that the JavaScript is being served from, so the API call is cross domain. The linked data API implementation, Elda, supports both the CORS and JSONP methods of cross-domain invocation. While CORS is generally better, it is not supported by Internet Explorer. Setting the datatype to “jsonp” is how jQuery selects the JSONP method. By default this adds an additional parameter, _ to the query with a timestamp, to ensure that the request is not cached. While the API should ignore this parameter, currently it doesn’t and this causes an error. Until this problem is fixed, we need to disable the cache-defeating _ parameter. In fact, we probably want to do this anyway, since the RESTful URL is idempotent, so caching is desirable.

We’ve split the job of invoking the LDA API into a library and application call. The library is something we’re still working on, but essentially it’s just a wrapper for the jQuery call, with some convenience functions for getting all resources event though, for example, the resources are paged. In app.js, we call that library:

bathing-water-quality-API

This will get us back an array of five bathing waters (_pageSize:5), using the bathing-water view augmented with two additional property paths.

Rendering the page

Once we have the data as a JSON object, it’s then a straightforward process of creating HTML from the data. In this case, I’m using the Foundation library to show a slide-show of the five selected bathing waters with the date and result of the most recent water quality assessment.

For more complex pages, it’s worth using a templating system, of which there are many to choose from. In this case, however, the markup is sufficiently straightforward that we can easily build it with sprintf:

bathing-water-quality-API-2

The code for this demo is available on github.

#TechTalk

Save

Save

Save

Save

Save

Save

Save