Related Items Bookshelf ("Browse This Shelf")
Installation & Administration Guide for Release 1.1


Technical Overview

The Related Items Bookshelf ("Bookshelf") is designed as java web application, in order to be hosted inside the Tomcat installation already used by Voyager WebVoyage. It is hosted inside the same "vwebv" tomcat instance for deployment simplicity, but is a separate web application.

Integration with WebVoyage consists of one new xsl file and two lines added to existing xsl files. The result of this code is to embed an <iframe> element, which loads the bookshelf, near the bottom of the WebVoyage record page. Should the bookshelf URL be incorrect or its web application have some bug or configuration issue, WebVoyage's normal operation should be unaffected.

The page loaded by this iframe consists of static HTML, Javascript and CSS files. The rest of the web application consists of a servlet (and related classes) supporting a set of JSON web services. The bookshelf makes AJAX calls to these web services to load Voyager's book data. It then utilizes the Google Book Search API to load links and cover images.

The Related Items Bookshelf website contains more on the design including an archicture diagram and a list of third-party libraries used.

Before You Begin

System Requirements

Make sure that you have read and understand the system requirements for the Voyager server as well as for user browsers.

General Tips

Documentation Conventions

In the example code below, I use {curly_brackets} to indicate values that you will have to change for your particular Voyager configuration. (Replace the whole string -- don't leave the curly brackets.) For example:

The directory name of your voyager installation, typically ending in 'db'.
The directory name of your WebVoyage skin, typically 'en_US'.

I also hide a few non-essential technical details away in tooltips; hover to view them.

Installation Instructions

Stop Tomcat

Note: Voyager is setup with two Tomcat instances, one for WebVoyage (called vwebv) and one for the backend web services (called vxws). This installation affects only the vwebv instance.

  1. Stop Tomcat.
    $ /m1/voyager/{xxxdb}/tomcat/vwebv/tsvrctl stop

Deploy the Web Application

The bookshelf is a java web application, designed to be hosted on "vwebv", the same Tomcat instance as WebVoyage.

  1. Backup (or delete) any previous versions of the bookshelf
    $ cd /m1/voyager/{xxxdb}/tomcat/vwebv/context
    $ ls -l
    (see date that "relatedItemsShelf" was created", i.e jan 1st 2009)
    $ mv relatedItemsShelf relatedItemsShelf.2009-01-01
  2. Create a directory for the web application
    $ mkdir /m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf
  3. Upload and/or copy the relatedItemsShelf.war file to that new directory
    1. IF you normally use a sudo command when editing files on the server, you will have to upload this file in two steps:
      • Use WinSCP (or a similar FTP program) to upload relatedItemsShelf.war to your home directory. For user John Smith, this directory is probably named something similar to /export/home/smithj or /home/smithj.
      • Copy the file into the relatedItemeShelf directory, substituting the path to your home directory:
        cp {home_directory}/relatedItemsShelf.war /m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf/
    2. OR, if you can write to that directory with your own login:
      • just use an FTP program to upload the relatedItemsShelf.war file there directly.
  4. Extract and delete the war file
    $ cd /m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf
    $ unzip relatedItemsShelf.war
    $ rm relatedItemsShelf.war

Configure Tomcat

Tell Tomcat how to load the new web application.

  1. Determine the hostname and port of your other Tomcat instance, the "vxws" instance that hosts Voyager's web services layer.

    View the contents of your WebVoyage web.xml file


    Look for the "context-param"s named XServiceHost and XServicePort. The associated "param-value"s tell you the host and port, respectively, of the vxws Tomcat instance. Write these two values down and close web.xml.

  2. Backup Tomcat's server.xml
  3. Add the bookshelf webapp "Context" to Tomcat's server.xml
    1. Open server.xml in a text editor.
    2. Look for these two lines near the end of the file:
    3. IN BETWEEN those two lines, insert the contents of the tomcat_server.xml_additions.txt file.
    4. Locate the docBase line in the code you just added, and edit it to reflect the name of your voyager instance:
    5. If you are running Voyager on a Windows server, alter your docBase to begin as a proper Windows path, i.e. c:/m1/voyager/.... See the docBase line above in the vweb Context element for how the path should begin.
    6. Locate the <Environment name="vxwsUrlBase" line in the code you just added, and edit the value to specify the correct URL (host and port, separated by a colon) to your vxws Tomcat instance. These are the XServiceHost and XServicePort values you just found.
      <Environment name="vxwsUrlBase" value="http://localhost:1234/vxws/" type="java.lang.String" override="false"/>
    7. Save the edited server.xml file.

Restart Tomcat

  1. Start Tomcat.
    $ /m1/voyager/{xxxdb}/tomcat/vwebv/tsvrctl start
  2. Wait 30 seconds.
  3. Test WebVoyage.

    Open your OPAC in a web browser and perform a search. Everything should work as it did before; the bookshelf has not yet been integrated into the OPAC.

Configure Apache

Apache Web Server (i.e. Apache httpd or just Apache) must simply pass the appropriate bookshelf URLs off to the vwebv Tomcat instance, just as it passes other vwebv traffic. Your Voyager server admins will probably have to do this step, and it will vary based on their Apache configuration policies.

  1. Determine which Apache configuration file contains your JkMount directives.

    Note: This has changed in a recent version of Voyager, possibly 7.2.1 or 7.2.2, and is still unsettled -- use your own best judgement. The following advice is adapted from Michael Doran's 7/7/10 post on Voyager-L, "IMPORTANT - Change to Tomcat vwebv Apache config file".

    View your deployed version of this Apache configuration file:

    1. In a typical "older" installation of Tomcat WebVoyage, the file contains this directive:

      # JKMounts
      Include conf/ConfiguredVirtualHosts/{xxxdb}.jkmounts.conf

      If so, your JkMount directives are located within that referenced {xxxdb}.jkmounts.conf file.

    2. In some "newer" releases of Voyager, your {xxxdb}_vwebv_httpd.conf file itself contains a single JkMount directive:

      # JKMounts
      JkMount /vwebv/* ajp13_lb_xxxdb_vwebv
  2. Configure Apache to let Tomcat handle bookshelf URLs

    The web server should be configured to forward any URL paths beginning with /relatedItemsShelf/ to the vwebv Tomcat instance. In whichever file you determined above contains the JkMount directives, add the following line:

    JkMount /relatedItemsShelf/* ajp13_lb_{xxxdb}_vwebv
  3. Restart Apache.

Integrate the Bookshelf into WebVoyage

Tell WebVoyage to include the bookshelf at the bottom of the bibliographic record page, below the holdings information.

  1. Upload or copy relatedItemsShelfFacets.xsl into the pageFacets directory.

    See Step 3 under Deploy the Web Application for how to upload a file to this directory. If you need to first upload it to your home directory and then copy it to the pageFacets directory, the copy step will look like:

    cp {home_directory}/relatedItemsShelfFacets.xsl /m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/pageFacets/
  2. OPTIONAL: Enable cover image loading

    By default, the bookshelf displays fake book covers -- stock images superimposed with the title and author. It also includes the capability to load real cover images from Syndetics Solutions or Google Book Search. Books for which real images are not available (generally older titles) continue to display the fake cover images.

    Enabling Syndetics requires that you have an existing relationship that allows you to access their book images. Syndetics provides customers with a "client code" used in this configuration.

    Enabling Google Book Search indicates your acceptance of its Terms of Service. This will enable both cover image display and links to 'About' and 'Preview' pages for applicable books.

    If you enable both, Syndetics cover images will be used along with links to Google Book Search pages.

    1. Backup relatedItemsShelfFacets.xsl.
    2. Open relatedItemsShelfFacets.xsl in a text editor.
    3. Find this six-line commented-out section:
        <span id="relatedItemsShelf_syndeticsClientCode" style="display: none;">CLIENTCODE</span> 
        <span id="relatedItemsShelf_useGoogleBooks" style="display: none;">true</span>
    4. To enable Syndetics:
      1. Edit the CLIENTCODE to match your Syndetics client code.
      2. Delete the <!-- and --> lines immediately above and below the line you just edited.
    5. To enable Google Book Search:
      1. Delete the <!-- and --> lines immediately above and below the <span id="relatedItemsShelf_useGoogleBooks" line.
    6. Save the edited relatedItemsShelfFacets.xsl
  3. Edit displayRecord.xsl
    1. Backup displayRecord.xsl
    2. Open displayRecord.xsl with a text editor.
    3. Find a section entitled "Specific Imports" with several <xsl:include ... /> statments:
      <!-- Specific Imports -->
      <xsl:include href="./contentLayout/cl_displayRecord.xsl"/>
      <xsl:include href="./contentLayout/display/display.xsl"/>
      <xsl:include href="./pageFacets/displayFacets.xsl"/>
      <xsl:include href="./pageFacets/resultsFacets.xsl"/>
    4. After the last of these <xsl:include ... /> statements, insert this new line:
      <xsl:include href="./pageFacets/relatedItemsShelfFacets.xsl"/>
    5. Save the edited displayRecord.xsl
  4. Edit displayStaff.xsl

    This file needs the same line you just added to displayRecord.xsl. It will not cause the bookshelf to appear on the staff (MARC) view.

    1. Backup displayStaff.xsl
    2. Open displayStaff.xsl with a text editor.
    3. Find a section entitled "Specific Imports" with several <xsl:include ... /> statments:
      <!-- Specific Imports -->
      <xsl:include href="./contentLayout/cl_displayStaff.xsl"/>
      <xsl:include href="./contentLayout/display/display.xsl"/>
      <xsl:include href="./pageFacets/displayFacets.xsl"/>
      <xsl:include href="./pageFacets/resultsFacets.xsl"/>
    4. After the last of these <xsl:include ... /> statements, insert this new line:
      <xsl:include href="./pageFacets/relatedItemsShelfFacets.xsl"/>
    5. Save the edited displayStaff.xsl
  5. Edit cl_displayRecord.xsl
    1. Backup cl_displayRecord.xsl
    2. Open cl_displayRecord.xsl with a text editor.
    3. In cl_displayRecord.xsl, find a section starting with <div class="recordContent> and ending with a closing </div>. It should look similar to this, however it may have additional lines inside:
      <div class="recordContent">
      	<!-- ## Action Box ## -->
      	<xsl:call-template name="buildActionBox">
      		<xsl:with-param name="pageRecordType" select="''"/>
      	<!-- ## Bibliographic Data ## -->
      	<xsl:for-each select="$Config">
      		<div class="bibliographicData">
      			<xsl:call-template name="buildMarcDisplay">
      				<xsl:with-param name="recordType" select="'bib'"/>
    4. Find the </div> that ends this section. It will probably be indented similarly to the <div class="recordContent> line that began the section. (Note that there may be other pairs of <div> and </div> in between; there is one in this example.)
    5. Just above the </div> that ends this section, add this new line:
      <xsl:call-template name="buildRelatedItemsShelf"/>
    6. Save the edited cl_displayRecord.xsl
  6. OPTIONAL: Add a Bookshelf Hint

    Patrons may not notice the bookshelf since it appears at the bottom of the bibliographic record page and it's rarely visible from the top. This step adds a small icon and link to the bottom of the "Action Box" on the right side of the record page, which simply scrolls down the page so that the bookshelf is visible.

    1. Backup displayFacets.xsl.
    2. Open displayFacets.xsl in a text editor.
    3. Find these lines at the very end of the file. (There may be additional empty lines in between.)
      <!-- ###################################################################### -->
    4. Just above the </div> line, insert the contents of the displayFacets.xsl_additions.txt file.
    5. Save the edited displayFacets.xsl

Test & Confirm

  1. Open up IE 7+ or Firefox 3+.

    Other browsers not yet supported and the bookshelf will not appear at all.

  2. Load up WebVoyage, perform a search and open a record page for an item cataloged with an LC call number.
  3. Scroll to the bottom of the page.

    The bookshelf should appear below the "Holdings Information" section and above the page footer.

  4. Click around. You should be able to:
  5. Test out the bookshelf on items with different locations or call number types.
  6. How'd it go?

    Please report any bugs or suggestions about the bookshelf or these instructions.

Please Register

A lot of time and effort went into developing this tool and making it adaptable to other libraries; the only "payment" I ask is an email letting me know what institution is testing it out. Thanks!

Advanced Configuration

This section describes OPTIONAL advanced configuration options for the Related Items Bookshelf.

Configure *When* the Bookshelf Appears

The Related Items Bookshelf displays items that are related to the primary item based on alphanumeric proximity to its call number. This makes sense for many common call number types (Library of Congress, Dewey), but not for others. For example, some libraries use special call numbers like "JOURNAL" for every journal, or use the first few letters of a serial title. In that case, items with similar call numbers may have no relevance to the primary item, and therefore the bookshelf would not be useful.

You may configure the bookshelf to appear (or not) based on the primary item's callNumber or locationCode, as listed in its MFHD. By default, the bookshelf is configured to appear for items in any location, whose call number appears to be standard LC based on the following very simple rules:

Advanced users may configure this filter as desired. The decision on which items should display the bookshelf is dependent on your library's collection, and on which collections you anticipate the it will be useful to patrons. The configuration itself requires some understanding of XSLT function syntax.

  1. Backup relatedItemsShelfFacets.xsl.
  2. Open relatedItemsShelfFacets.xsl in a text editor and locate the following line:
    <xsl:when test="(string-length($callNumber) > 3) and not(contains($callNumber, '/')) and not(contains($callNumber, ':'))">
  3. Add, remove or change any clauses inside the test expression according to your needs.
  4. Save the edited cl_displayRecord.xsl

Configure *Which Items* the Bookshelf Includes

The goal of the Related Items Bookshelf is to display only those items "related" to the initial item by proximate call number. However Voyager's call number browse functionality, which the bookshelf uses to find relevant items, returns items with any call numbers that are alphanumerically related, even if the call numbers are of different types (LC, SUDOC, Dewey, etc.) Therefore the bookshelf includes additional custom logic to eliminate irrelevant items as best it can, which due to other Voyager search limitations, can only examine the call number or heading type. (A detailed explanation of the problem is here.)

Two filtering methods are supported (individually or in combination): call number and "heading type". Only call number filtering is enabled by default. Note that each filter you enable will slow down the item loading process to some degree.

Filtering Bookshelf Items by Call Number

By default, the bookshelf filters out items which appear to have non-LC call numbers, based on the same simplistic rules described the previous section.

An advanced user may configure the bookshelf to include other items. As with the decision on when to display the bookshelf at all, this decision is dependent on your library's collection. This configuration requires understanding of Java regular expressions.

  1. Backup server.xml.
  2. Open server.xml in a text editor and locate the following section:
    <Environment name="callNumberFilterNames" value="govDocs,fiction" type="java.lang.String" override="false"/>
    <!-- Exclude probable Government Documents: anything with a colon or a slash -->
    <Environment name="callNumberFilter.govDocs" value=".*[:/].*" type="java.lang.String" override="false"/>
    <!-- Exclude 'fiction call numbers': the start of an author's last name: three characters max, ending with a letter -->
    <Environment name="callNumberFilter.fiction" value=".{0,2}[a-zA-Z]" type="java.lang.String" override="false"/>
  3. Add, remove or modify any of the environment variables in this section according to your needs:
  4. Save the edited server.xml
  5. Stop Tomcat, wait 20 seconds, and then Restart Tomcat.

Filtering Bookshelf Items by Matching Heading Type (Experimental)

The term "heading type" here does not refer to LC Subject Headings. Rather, it's a field returned by a call to Voyager's SearchResultsService. Its exact meaning is unclear.

By default, the Related Items Bookshelf ignores this field. However you can configure it to filter out items which have a different headingType than the primary item on the record page. Consider this a highly experimental "magic button": it may eliminate some irrelevant items, but it also may eliminate some relevant ones. If you're adventurous, try and see.

  1. Backup server.xml.
  2. Open server.xml in a text editor and locate the following section:
    <!-- Filters bookshelf items to match the "headingType" of the primary item. -->
    <Environment name="useHeadingTypeFilter" value="false" type="java.lang.String" override="false"/>
  3. To enable the headingType filter, change the value attribute to true.
  4. Save the edited server.xml
  5. Stop Tomcat, wait 20 seconds, and then Restart Tomcat.

Configure Administrative Access

The bookshelf can configured in limited ways while it is running, by making simple web requests to a special URL. These requests are only accepted from trusted IP addresses, specified in a server.xml configuration property. The default setting only allows access from the server machine itself. To broaden or disable this access:

  1. Open server.xml in a text editor.
  2. Look for this line:
    <Environment name="adminIpFilter" value="," type="java.lang.String" override="false"/>
  3. To enable access from additional trusted machine(s), add their IP addresses, comma-separated, as in:
    <Environment name="adminIpFilter" value=",111.222.333.444," type="java.lang.String" override="false"/>
  4. To disable access even from the WebVoyage server itself, erase the value:
    <Environment name="adminIpFilter" value="" type="java.lang.String" override="false"/>
  5. Stop Tomcat, wait 20 seconds, and then Restart Tomcat.

Enable Google Analytics usage tracking

If you have a Google Analytics account, you can track (anonymously) usage of the bookshelf, to see how patrons are using it. This feature is disabled by default.

  1. Backup relatedItemsShelfFacets.xsl.
  2. Open relatedItemsShelfFacets.xsl in a text editor.
  3. Find this three-line commented-out section:
    	<span id="relatedItemsShelf_GA_trackerId" style="display: none;">UA-0000000-1</span>
  4. Edit the UA-0000000-1 code to match your Google Analytics account number.
  5. Delete the top and bottom lines so that only the <span> line remains.
  6. Save the edited relatedItemsShelfFacets.xsl

Customize Voyager Data Retrieval

In some cases you may wish to change the data fields retrieved by the Related Items Bookshelf from Voyager. This requires Java programming ability. Two bookshelf classes can be overridden via configuration properties, rather than recompiling the entire codebase. These classes are:

A search result returned from a call to SearchResultsService, after a call-number browse search via SearchService. Used to load the initial list of items with title and author data.
The full bib record returned from a call to GetHoldingsService. Used to enrich the info popup box with additional information after an extended mouseover.
  1. Write a Java class that replaces one of the classes above.
  2. Compile the class and upload it to:
  3. Add an Environment property to server.xml declaring the new class. See the Server.xml Configuration Properties appendix for syntax.
  4. Stop Tomcat, wait 20 seconds, and then Restart Tomcat.

Administration Guide

Administrative Access

Bookshelf administration control is only available from the IP addresses you configured in server.xml.

  1. If you have limited access to the Voyager server machine (the default), you will need a server-side HTTP client to perform administrative actions. Common clients include curl and wget. You invoke administrative actions from the server command line, as in:
    $ curl http://localhost/relatedItemsShelf/someAdministrativeAction
    $ wget -O - http://localhost/relatedItemsShelf/someAdministrativeAction
  2. If you have enabled access from a desktop machine (with a web browser), simply load the appropriate administrative URL as you would any webpage.

Configure Application Logging

The Related Items Bookshelf application logs key operations to a text file:


When the Bookshelf application is first accessed after Tomcat is started, the log "level" is set at INFO, meaning that only major events or problems are logged to this file. If you are trying to investigate a problem, it may be useful to temporarily change the logging level to record more fine-grained activity.

To change the log level:

  1. If Tomcat has been recently restarted, first initialize the bookshelf by loading any WebVoyage record page that includes it.
  2. Determine the appropriate log level. The default (producing limited output) is INFO. The most verbose, recommended while you are debugging a problem, is ALL. The full list is: OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL.
  3. Load the following URL as described in Administrative Access, changing server hostname and the level value as desired.
  4. Note: If you change the level to allow more output, remember to change it back when you are done, or your log file will grow to a large size very fast.

Support & Contact Information


Adapted from Michael Doran's New Books List installation instructions, with permission:

I am an Emerging Technologies Librarian with a full time job quite apart from creating, enhancing, documenting, distributing, and supporting the Related Items Bookshelf. Please keep that in mind and thoroughly read these installation instructions, and the program comments, before contacting me for help.

This is not meant to discourage you from contacting me, particularly in regard to bugs or issues that may impact other users of the software. I am also very interested in hearing how the installation instructions and other documentation can be made more clear or otherwise improved.

Technical information and a list of open issues are also available on the Related Items Bookshelf website.

Contact Information

Please send bug reports, suggestions, and other feedback to:

Maccabee Levine
Polk Library
University of Wisconsin Oshkosh

Server.xml Configuration Properties

These bookshelf configuration properties are defined Environment elements in server.xml, as in:

<Environment name="{name}" value="{value}" type="java.lang.String" override="false"/>

Name Description Required? Example
vxwsUrlBase Path to the Voyager VXWS server. See Configure Tomcat. Yes http://localhost:1234/vxws/
adminIpFilter IP addresses allowed to access admin functions. Comma-separated. Note: no admin access is accepted until the bookshelf is first loaded following a Tomcat restart. See Administrative Access. No; if absent, no admin access is allowed.,111.222.333.444,
useHeadingTypeFilter Filters bookshelf items to match the "headingType" of the primary item. See Configure Which Items the Bookshelf Displays. No; if absent, defaults to 'false'. true
callNumberFilterNames Names, comma-separated, of call number filters defined as separate configuration properties. See Configure Which Items the Bookshelf Displays. No; if absent, no call number filters are used. govDocs,fiction
{name_of_a_call_number_filter} Java regular expression defining a call number pattern to exclude. See previous row and Configure Which Items the Bookshelf Displays. Required if named by the callNumberFilterNames property. .*[:/].*
searchResultClassName Specifies the full class name of a Java class to substitute for edu.uwosh.polk.voyager.SearchResult. See Customize Voyager Data Retrieval. No; if absent, use the standard SearchResult class. MyCampusSearchResult
holdingsRecordClassName Specifies the full class name of a Java class to substitute for edu.uwosh.polk.voyager.HoldingsRecord. See Customize Voyager Data Retrieval. No; if absent, use the standard HoldingsRecord class. MyCampusHoldingsRecord