Ready to Learn?Ex Libris products all provide open APIs

General Purpose

Records exported from an ILS and loaded into Primo usually include location and availability status information for the items that are linked to the bibliographic record. In many cases, the availability statuses are out of date. The RTA Plug-in mechanism allows you to retrieve current availability statuses from the source system (such as an ILS) and display them to the users.

Note: The RTA Plug-in mechanism does not replace the existing RTA Adapter mechanism, which still provides real-time availability statuses for Aleph, Voyager, and III Millennium. If you are looking to create your own RTA program, Ex Libris recommends that you use the RTA Plug-in mechanism, which is much easier to implement than the RTA Adapter mechanism. Any implementations that currently use the RTA Adapter mechanism should function as they had previously.

Motivation: In order to the current availability status of a record, it is assumed that you have access to an API (which is usually part of your ILS system) that can query for the availability status of a specific record. Because every API requires different inputs and outputs, the RTA plug-in mechanism allows you to create RTA plug-ins to support these differences.

Source System API Requirements

In order to implement an RTA plug-in, you will need access to an API that allows you to query for the current availability status for a specific record on the source system.
Example #1

This API receives the unique ID of a record that exists in the ILS and sends information about each location and the availability status for the requested record. Note that additional data may exist in the response, but the system will probably not use it.
Example Input:
http://www.mydoamin.com/availbilityAPI?recordId=1234

Example Output (XML response):

<locations>
    <location>
        <libraryCode>UEL</libraryCode>
        <subLocation>ADR</subLocation>
        <callNumber>012.920</callNumber>
        <availability>available</availability >
    </location>
    <location>
        <libraryCode>UEL</libraryCode>
        <subLocation>RBL</subLocation>
        <callNumber>022.XXX</callNumber>
        <availability>unavailable</availability>
    </location>
</locations>


Example #2

The API receives a unique ID for a record that exists in the ILS and additional information about the location and sends back the availability for this location in the response message.
Input Example:
http://www.mydoamin.com/availbilityAPI?recordId=1234&libraryCode=UEL& subLocation=ADR&callNumber=012.920

Output Example (XML response):

<availability>
    <status>true</status>
<availability>


An acceptable API may permit many other options, but it is important to make sure that your RTA plug-in can communicate with the API and retrieve up-to-date availability statuses for a record.

Integration & Implementation

Registering Your Plug-In

After you have created and installed your RTA plug-in on the Back Office and Front End servers, you can start the registration process in the Back Office.
To register your plug-in with the system, you must configure the following mapping tables:

  • Plugins
  • Plugins Parameters

The Plugins Mapping Table

This mapping table registers the plug-ins with the system. To register a plug-in, you must enter the following fields:

  • Name – The unique name for your plug-in, which is used by the Plugins Parameters mapping table.
  • Class - a fully qualified name of a class that implements the PhysicalRTAPlugin interface (also known as the plug-in implementation).
  • Type – Defines the type of the plug-in that you are registering. Choose the value: RTA.

Figure 1. Plugins Mapping Table

The Plugins Parameters Mapping Table

This mapping table defines the parameters that the system passes to your plug-in. To define a parameter for your plug-in, enter the following fields:
  • Param Name – The name of the parameter that you want to pass.

  • Param value – The value of the parameter to pass to the plug-in.

  • Plugin – The name of the plug-in (taken from the Plugins mapping table) to which this parameter name and value will be passed.


Figure 2. Plugins Parameters Mapping Table

The following table lists the parameters that are required for each RTA plug-in. If you do not define them, the plug-in will not work:
Table 1. Required RTA Parameters

Param NameParam ValueExample
SourceSystemThe system uses this value to determine which RTA plug-ins it will use to process
the records that display in the Brief Results page in the Front End.
For each record, the system compares the value of the record/control/sourcesystem element
with the value of this parameter and passes only the matching records to the RTA plug-in.
SourceSystem = Talis
IdentifierXpathThis parameter contains the XPath reference point in the PNX record.
You can configure this path to point to any value in the PNX record.
The path should be constructed like the following:
record/<section>/<field>
IdentifierXpath = record/control/sourcerecordid
  <?xml version="1.0" encoding="UTF-8"?>
      <record>
          <control>
              <sourcerecordid>000365625</sourcerecordid>
              <sourceid>primo_aleph</sourceid>
              <recordid>primo_aleph000365625</recordid>
              <sourceformat>MARC21</sourceformat>
              <sourcesystem>Aleph</sourcesystem>
          </control>
          …
      </record>
In this example, the system passes the value 000365625 to your
plug-in so that your plug-in can request availability information for the record from the RTA API.

In addition to the required parameters above, you can pass additional parameters to use in your plug-in. For example, the PicaRTAPlugin and RTAPluginSymphony plugins can also use the following parameters:

  • Debug – Enables debug information to be sent to the log.
  • Timeout – The timeout on the request to the Pica ILS. If no result returns from the ILS before the timeout is reached, the request stops and the availability status is not updated.

Deploying Your Changes

Any changes made to the above mapping tables require you to deploy the changes to the FE machine. To deploy the changes, select the RTA Configuration option and click Deploy on the Deploy All page in the Back Office.


Figure 3. RTA Configuration Deploy

Note: If you are using the Test RTA Plugin utility in the Back Office, you do not need to deploy the RTA configuration. For more information, see Testing Your Plug-In.

Setting the RTA Base URL

If you do not want to hard code the base URL of the source system's API in your plug-in, you will need to set the RTA base URL on the Institution page in the Back Office for each institution. For each PNX record, your plug-in will receive in the Library object the RTA base URL to use, based on the configured institution and the institution marked in the record. Any changes to the RTA base URL require you to deploy the institution.

Note: Ex Libris recommends that you allow the system to pass the RTA base URL to your plug-in to provide flexibility in case you need to modify the URL and to ensure that you are using the correct URL for each institution.

Implementation Steps

Use the following procedure to create a new RTA plug-in:

  1.     Copy the needed JAR file including the needed interface from (on BO machine) into your development environment.:

    a) up to Primo version 4.5 - $primo_dev/ng/primo/home/system/publish/client/primo_common-api.jar

    b) from Primo version 4.5 and on
         $primo_dev/ng/primo/home/system/tomcat/publish/webapps/primo_publishing#admin/WEB-INF/lib/primo-common-api-<version>.jar
     
  2.     Implement the PhysicalRTAPlugin interface.
  3.     Wrap your RTA class in a new JAR file.
  4.     Install your new JAR file and any other needed third-party JAR files, in the following directory on all of the Back Office and Front End servers:
        $primo_dev/ng/primo/home/profile/publish/publish/production/conf/plugins/rta
  5.     Configure the Plugins and Plugin Parameters mapping tables described below.
  6.     Deploy the RTA configurations in the Back Office.
     

Implementing the PhysicalRTAPlugin Interface

To implement the PhysicalRTAPlugin interface, you will need to copy a JAR file to your development environment.

Class Files

com.exlibris.primo.api.plugins.rta.PhysicalRTAPlugin
com.exlibris.primo.api.plugins.rta.RTARequest
com.exlibris.primo.api.plugins.rta.Library
com.exlibris.primo.api.common.IPrimoLogger
com.exlibris.primo.api.common.IMappingTablesFetcher

PhysicalRTAPlugin Interface

For this interface, you will need to implement the following functions to implement your RTA plug-in:

  1. init()
  2. updateAvailbility()

init()

This function initializes your RTA plug-in and provides the plug-in with access to utilities and the parameters defined in the Plugins Parameters mapping table. In addition, you can open or store any needed data for the plug-in.

public void init(IPrimoLogger logger,
         IMappingTablesFetcher mtFetcher,
         Map<String, Object> params);



The system will call this function only in the following situations:

  •     The Front End is restarted.
  •     The RTA configuration is deployed.


Note: If you are using the Test RTA Plugin utility in the Back Office, the system will call this function each time a user executes the utility for the RTA plug-in.

Each time the system calls this function, it passes the following parameters:

    IPrimoLogger – an object that allows you to write information concerning the execution of your plug-in to the Primo log files. When executed on the Back Office server for RTA tests, the system sends the output to the publishing_server.log in the BO machine. When executed on the Front End server, the system sends the output to the library_server.log in the FE machine.
   

public interface IPrimoLogger {
        public void setClass(Class<?> clazz);
        public void info(String msg);
        public void warn(String msg);
        public void warn(String msg, Exception e);
        public void error(String msg);
        public void error(String msg, Exception e);
    }


    IMappingTablesFetcher – An object that allows you to retrieve values from any mapping and code table by specifying a table name. The object returned is a List<Map<String, String>> object, where each object in the List represents a row in the mapping or code table and each row is a Map object, where the key is the column name and the value is the value of that column's entry in the mapping or code table.
   

   public interface IMappingTablesFetcher {
     
        public List<Map<String, String>> getTableRows(String tableName);
    }




    For example:
   

 

    myCodesMap = new HashMap<String, String>();
     
    List<Map<String, String>> rows = mtFetcher.getTableRows("ILS Library Codes");
     
    for (Map<String, String> row : rows) {
       String libraryCode = row.get("Library Code");
       String primoCode = row.get("Primo Code");
     
       myCodesMap.put(libraryCode, primoCode);
    }




    Map<String, Object> – An object that contains all of the parameters configured for your plug-in in the Plugins Parameters mapping table. The key is the parameter name and the value is a string containing the parameter's value.
 

updateAvailability()

The system calls the updateAvailability() function each time your plug-in is needed to update availability statuses for a record. The plug-in uses this function to communicate with the RTA API to get up-to-date availability information.
public void updateAvailability(List<RTARequest> rtaRequests);

Depending on the RTA API, this function will need to send the records identifier to the API and be able to parse the availability statuses received from the API. After you have parsed the response from the API, you will use this information to update the statuses received in the List<RTARequest> object, which contains a list RTA requests.
For example, a snippet of this function may appear as follows:

public void updateAvailability(List<RTARequest> rtaRequests) {
 
    for (RTARequest request : rtaRequests) {
 
         // A function calling your API, passing it the record ID
         // and receiving back information about availability status.
         results = getAPIResultsForRecord(request.getRecordIdentifier());
 
         for (Library library : request.getLibraries()){
 
            // Find the status for the given library
            // in the returned API results.
            status = getAvaliabilityStatusForLibrary(library, results);
 
            library.setHoldingStatus(status);
         }
    }
}



Note: The getAPIResultsForRecord() and getAvaliabilityStatusForLibrary() functions shown above are not predefined. You will need to create similar functions to implement your plug-in.

Using Constructors



Because the system creates your RTA plug-in by invoking the empty constructor, your plug-in must contain an empty constructor. The following rules apply to constructors defined in your plug-in:

  •     No constructors – Java will default to the empty constructor.
  •     Multiple constructors – In addition to the other constructors, you must also include the empty constructor.
     

When is the RTA Plug-In Initialized?



After you register your plug-in, the system will create the plug-in's object once in the following cases:

  •     The Front End is restarted.
  •     The RTA Configuration is deployed to the Front End.
  •     Each time the Test RTA Plugin utility executes the plug-in in the Back Office. Note that the system creates and destroys this object on the Back Office server only.


After the plug-in's object is created, the system will call the init() function to initialize your plug-in. This object will serve all RTA requests for the intended source system. Because this is a Singleton object, the code will have to run in parallel to handle simultaneous requests for real-time availability.
Caution: When implementing a Singleton object, you should avoid using global members in your Java code to prevent parallel requests from overwriting a global member's data.
 
 

 

Mapping ILS Institution and Library Codes to Primo Codes

It is important to note that the institution and library codes that the system sends to the RTA plug-in in the Library object are the Primo codes, which may be different from the codes defined in the source system. If this is the case for your source system, you will need to map these values in your plug-in. To map these values, you can use any of the following methods:

  • Use the IMappingTableFetcher object received in the init() function to access the following mapping tables:
    • ILS Institution Codes – maps the ILS Institution field to the Primo Institution field.


      Figure 5. ILS Institution Codes Mapping Table
       
    • ILS Library Codes – maps the Library Code field to the Primo Code field.


      Figure 6. ILS Library Codes Mapping Table
       
  • Use the Plugins Parameters mapping table to configure and pass the library and code mappings to the plug-in.
  • Create a file that contains the necessary mappings and store it with your plug-in.

 

RTARequest

Each RTARequest object represents one PNX record that requires availability status updates in the Front End. You will need to update the availability status for each RTARequest object.

public class RTARequest {

    private String primoRecordId;

    private String recordIdentifier;

    private List<Library> libraries;

}

This object contains the following members:

  • primoRecordId – The PNX primo record ID. This member is not usually used by your plug-in. The RTA mechanism uses it.
  • recordIdentifier – This is the value received from the PNX for the configured IdentifierXpath parameter.
  • libraries – A list of libraries in the current PNX record, where each Library object contains location information and holdings status. Your plug-in will need to update the holdingStatus field in the Library object for each library in the list.

Request Timeouts

Because requests are made to an API on another server, it is important to prevent hanging requests in your code. To prevent hanging requests, it is important to utilize the following timeout parameters for the type of connection the API uses:

  • Connection timeout – If it takes too long to connect to the API, cancel the request.
  • Read timeout – If it takes too long to read the response, cancel the request.


For example, if you are working with a URL-based API, you can use Java's URLConnection class:

 

URL url = new URL(pUrl);

    URLConnection connection = url.openConnection();

    connection.setConnectTimeout(conTimeout);

    connection.setReadTimeout(readTimeout);

 

Instead of hard coding timeout values in your plug-in, you can use the Plugins Parameters mapping table to set and pass these values to your plug-in. In most cases, these values should not be set higher than one to two seconds. If they are set too high, the performance of the Front End may be affected.


 

Library

The Library object, which the system passes to your plug-in, represents a single library within a PNX record. It contains the holdings status that is currently stored in the PNX record. Your plug-in is responsible for setting the correct status for this object.

public class Library implements Cloneable {


    private String institution;

    private String libraryCode;

    private String collection;

    private String callNumber;

    private String rtaBaseURL;

    private HoldingStatus holdingStatus;

}

This object contains the following members:

  • Institution
  • Library code
  • Collection
  • Call number
  • Holdings status – The valid values are Available, Unavailable, and Check holdings.
  • RTA base URL – For each library, the system passes the RTA base URL configured in the Institution wizard to the plug-in.

 

The availlibrary PNX field

The system uses the availlibrary field in the display section of the PNX record to store the location of the items that are linked to the record. In addition, it includes a summary availability status for all of the items at a specific location. A PNX record can have one or more availlibrary fields. For example, the <availlibrary> tag exists in the display section of the PNX record as follows:

<display>

    <type>book</type>

    <title>Approaches to insanity; a philosophical &amp; sociological study.</title>

    <creator>Jeff Coulter</creator>

    <availlibrary>

        $$IREEF$$LLUMD$$1Book$$2(BD161 .E23 1967 )$$Savailable$$31$$40$$5N$$60$$XPRM50$$YLUMD$$ZUMDBK

    </availlibrary>

    <availlibrary>

        $$IVOL$$LPBRIG$$1Gen $$2(QB980 .1985 )$$Savailable$$31$$40$$5N$$60$$XPRM50$$YPBRIG$$ZGEN$$9ONLINE

    </availlibrary>

</display>

In order for the system to display up-to-date availability information, your RTA plug-in must update the availlibrary field. The system will pass to the RTA plug-in a Library object that contains the following parsed values from the availlibrary field:

  • $$I – Institution
  • $$L – Library code
  • $$1 – Collection
  • $$2 – Call number
  • $$S - Holding status (the availability status: available/unavailable/check_holdings)
    Your RTA plug-in must use the information that it receives from the API on the source system to update the availability status in the Library object.

 

Testing your plugin

The Test RTA Plugin utility in the Back Office allows you to test your plug-in prior to deploying it to the Front End.



Figure 7. Test RTA Plugin Example
To test your plug-in with this utility, select your plug-in from the RTA Plug-in field, enter a record ID in the PNX Record ID field, and click Execute.

The output should contain the updated availability status for each library that exists in the PNX record.

Notes:

  •     Because the test mechanism automatically detects any change to RTA registration, there is no need to deploy the RTA configuration prior to running RTA tests in the Back Office.
  •     Before you can test your plug-in, you must install the necessary JAR files on the Back Office server and register your plug-in with the Plugins and Plugins Parameters mapping tables.