Ready to Learn?Ex Libris products all provide open APIs

Tech Blog

 

Using the Alma APIs with Node.js

Josh Weisman on November 1st, 2015

In the past couple of years, Node.js has become quite popular. With its cross-platform support, powerful package manager, and asynchronous architecture, Node is the environment of choice for many greenfield applications today.
 
This simple example can get you started using the Alma APIs in a Node.js application. Since the Alma REST APIs return JSON natively and use accepted standards, it's pretty straightforward to integrate them into your Node app. Let's get started!

Stack

This example uses a standard Node stack, including: 
  • Node.js which includes the runtime and the package manager
  • Jade as the template engine for the views
  • Express as the web framework
  • And of course, Bootstrap for the front-end framework
There are many getting started guides on the web, so if this is your first Node app, you'll find plenty of resources.

Functionality

For our simple example, we'll develop scan-in functionality, which takes an item barcode and shows the book's details. We also provide the ability to scan in the item, and the application will provide details from Alma about the item's destination, requests, etc.
We make use of the item details and scan in APIs from Alma.

Scan-in Form

After using the Express scaffolding, we have a basic web application. We replace the default layout.jade file with a Jade Bootstrap-based layout to make our small app a bit more presentable.
Now we're ready to build our form. Under the views folder, we create a scan-in folder with an index.jade file inside. The template contains the form which will be used to scan in an item's barcode.

Scan In Form

Controller and Alma.js Library

Once the form is built, we need to create a controller and begin to make our calls to the Alma API. For that, we add a new route in our app.js file to refer to the scan in controller:
var scanin = require('./routes/scan-in');
We create a scan-in.js file in the routes folder, and add a handler for the “get” action:
/* GET */
router.get('/', function(req, res, next) {
  getLibraries(
    function(err, data) {
      if (err) return next(err);
      res.render('scan-in/index', {
        title: 'Scan In Item',
        libraries: data
      });
    }
  );
});
The get function retrieves a list of libraries from Alma to populate a list box with the available libraries. The getLibraries function in turn calls a helper library for Alma API requests which we've called alma.js. The helper library exposes two methods, one for GET requests and one for POST requests, which wrap a function called performRequest.
The performRequest function handles all of the communication with the Alma API. We'll take a look at some of the more important parts of the code.
First, we add the relevant headers required for Alma APIs.
function performRequest(endpoint, method, data, callback) {
  var dataString = JSON.stringify(data);
  var headers = {
    'Authorization': 'apikey ' + apikey,
    'Accept': 'application/json'
  };
  if (method != 'GET') {
    headers['Content-Type'] = 'application/json';
    headers['Content-Length'] = dataString.length;
  }
Then we set the options required for the request:
  var options = {
    uri: (endpoint.substring(0,4) ==
        'http' ? '' : host + path) + endpoint,
    method: method,
    headers: headers
  };

Finally, we call the request function provided by the Request Node package and handle the error or success response.
  request(
    options,
    function(err, response, body) {
      if (!err && ('' + response.statusCode).match(/^[4-5]\d\d$/)) {
        console.log('Error from Alma: ' + body);
        var message;
        try {
          var obj = JSON.parse(body);
          message = obj.errorList.error[0].errorMessage + " (" + obj.errorList.error[0].errorCode + ")";
        } catch (e) {
          message = "Unknown error from Alma.";
        }
        err = new Error(message);
      }
      if (err) callback(err);
      else callback(null, body);
    });
  }

Posting the Scan-In Request

Once the library and circulation desk are filled in, we submit the Scan In form. The POST handler in the scan-in.js controller receives the request. Since we have a few calls in Alma that need to be made, and we don't want to wind up with nested callbacks, we use the Async Node package to handle the control flow. The code does the following:
  • Retrieves the library list in order to rebuild the form
  • Retrieves the item record based on the barcode
  • Sends a scan-in request to Alma and processes the result
  • Returns the view with the information retrieved from Alma
Based on the callback model inherent to Node, we can handle errors which might return from Alma. In this example, Alma informed us that an invalid barcode was provided:
if (err) {
  if (err.message.indexOf("401690") > 0 ||
      err.message.indexOf("401689") > 0)
    return res.render('scan-in/index', {
      title: 'Scan In Item',
      error: "Invalid barcode",
      libraries: libraries
    });
}

Scan In Fail

If all goes well, we can display the book title and author returned from Alma. We also display the information pertinent to the scanned in item; for example, if the book was requested or is in transit.
As an added treat, we use the Google Book API to retrieve the URL of a book cover thumbnail via AJAX and display it next to the book title.

Scan In Success

Wrap Up

Hope this example is helpful for those looking to get started with Node and Alma. Check out the full code sample on Github.
 
Github