Building the Alibris Application
The purpose of the Alibris application is to allow a library to upload a tab separated file of titles available in a particular topic area from Alibris, see which titles the library does not own, and then select titles for purchase. The first thing the application does is generate a form which allows a user to input their library's OCLC symbol and upload a tab separated (TSV) file to the server
The application takes the TSV file and places it on the server. Then it loops through each of the lines in the TSV file to extract basic metadata about the item to check to see if the library owns the item. Using WorldCat Search API, for each item the application performs a search for library holdings based on the item's ISBN and the library's OCLC symbol. If it finds a match then the item is ignored. It it does not find a match then it performs an SRU search for an exact match of the title limited to the library's OCLC symbol. If it doesn't find a match then it uses the metadata to retrieve a single MARC bibliographic record for the item and extracts metadata such as the OCLC Number from this. It then presents the user with a table of all the items from the TSV file which the library does not own and for which a matching WorldCat records could be located.
The user can then check off the items which they wish to purchase and click the "Place Order" button.
The application then performs and AJAX action using the JQuery library which gathers data from the form and page and builds a JSON object of OCLC Numbers, and prices which is sent to a separate PHP script that processes this and interacts with the prototype Acquisitions web service. The PHP script creates a JSON object that represents a new order and PUTs this to the Acquisition web service which creates a new order. The script retrieves the ID of the new order and then loops through all the items to be added to the order and creates a JSON object for each and PUTs it to url for the items in the newly created order. This adds each item to the order. When this is successfully completed the PHP script sends back a JSON object containing a success message and an HTML list of all the order items. The original application page displays a dialog window created with JQuery-UI that shows the order was successfully created and all the items that are part of the order.
Ideally we'd like this application to also send the order information to Alibris as well. However we haven't worked out the best way to make this happen yet. Alibris doesn't have a public order API. However, they do have some business to business web services that might allow us to create an order within their system but we haven't had a chance to work with that yet. Alternatively, we could create a tab or comma separated file of all the items on the order and send this as an email. As of yet we haven't determined which of these approaches is the best fit.
This particular application presented the most challenges of all the applications I built. One aspect of this was it was the first application I built. Another was the fact that it doesn't use an external web service for its initial data. Instead it requires a spreadsheet which conforms to a specific format be uploaded. This is a major usability obstacle because user of the application have to make sure that the item uploaded conforms to the appropriate format. Otherwise the application will fail.
Additionally, having to upload the file to an actual server requires that the server be appropriately configured to allow the application to create files on it. This particular configuration might be a serious hurdle to libraries wanting to implement this script. I considering using something like GoogleDocs as a holding area for these files but discarded that idea due to privacy concerns and the need to have a Google account. Currently, I'm wondering if load the files into a NoSQL database might be a possible solution.
Another issue with this application was the performance and speed of using WorldCat Search API to see if library held a particular item. I spent a lot of time thinking about what the most efficient way would be to check this for a large group of items. Basically it boiled down to two possible approaches:
- Use the holdings Request Type with and ISBN for each item
- Do an SRU search by ISBN for all the item ISBNs
While the second approach seemed like it would be potentially speedier and reduce load of WorldCat Search API, it also seemed the more challenging to work with. This is because this type of search would get me records for items that the library already owns and I need items that the library doesn't own. As a result I decided to go with the first approach and basically check for each item to see if the library had holdings. For a large dataset this is painfully slow. I'd like to improve this but haven't had time to consider way to optimize performance.
The final challenge that this application presented was interacting with the prototype acquisitions web service to create the order. Working with a REST service that was capable of performing write operations was new for me. I had to use HTTP methods and headers as part of my code. This meant that I couldn't use older code that used the SimpleXML PHP library. I could've simply switched to using PHP CURL. However, I decide that the syntax for PHP CURL was more convoluted than I liked. The result was I ended up using the Zend Framework to make all of my REST web service calls. The framework has a nice library that allows developers to take advantage of all the bells and whistles of HTTP including Headers and methods. Plus the syntax is object oriented which makes it slightly easier to both work with and teach from.
- the application was likely to interact with a WSKey protected version of the service which would mean performing this interaction via a server side script nonetheless.
- I wanted to make the create order code more versatile and reusable.
So I chose to keep it as a separate PHP page. The last challenge that this application created was dealing with the fact that the JSON have fields with strict possible values, which were unknown to me. A good example of this was the library location field which has to be set when an order is created. Although I ended up merely looking up the possible values of this field for my test library WMS instance and hard coding an appropriate one, the experience made me realize that it is important to think about the suite of services that a developer will need to perform a given task. Otherwise key tangential but necessary services will be missing and make the development process more cumbersome.
Even with all the challenges building this application was an extremely worthwhile experience because it allowed me to learn about using new types of services, working in a new framework, and how to collaborate with external partners.
Senior Product Analyst