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.
Make sure that you have read and understand the system requirements for the Voyager server as well as for user browsers.
sudo command, as below.
$ sudo su - voyager
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:
{xxxdb}{skin}I also hide a few non-essential technical details away in tooltips; hover to view them.
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.
$ /m1/voyager/{xxxdb}/tomcat/vwebv/tsvrctl stop
The bookshelf is a java web application, designed to be hosted on "vwebv", the same Tomcat instance as WebVoyage.
$ 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
$ mkdir /m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf
sudo command when editing files on the server, you will have to upload this file in two steps:
/export/home/smithj or /home/smithj.cp {home_directory}/relatedItemsShelf.war /m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf/
$ cd /m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf
$ unzip relatedItemsShelf.war
$ rm relatedItemsShelf.war
Tell Tomcat how to load the new web application.
View the contents of your WebVoyage web.xml file
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/WEB-INF/web.xml
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.
/m1/voyager/{xxxdb}/tomcat/vwebv/conf/server.xml
</Context> </Host>
docBase line in the code you just added, and edit it to reflect the name of your voyager instance:
docBase="/m1/voyager/{xxxdb}/tomcat/vwebv/context/relatedItemsShelf"
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.<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"/>
$ /m1/voyager/{xxxdb}/tomcat/vwebv/tsvrctl start
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.
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.
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:
{xxxdb}_vwebv_httpd.conf
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.
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
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
Tell WebVoyage to include the bookshelf at the bottom of the bibliographic record page, below the holdings information.
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/pageFacets/
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/
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.
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/pageFacets/relatedItemsShelfFacets.xsl
<!-- UNCOMMENT THIS LINE AND CHANGE THE CLIENTCODE TO ENABLE SYNDETICS IMAGES <span id="relatedItemsShelf_syndeticsClientCode" style="display: none;">CLIENTCODE</span> --> <!-- UNCOMMENT THIS LINE TO ENABLE GOOGLE BOOK SEARCH LINKS AND IMAGES <span id="relatedItemsShelf_useGoogleBooks" style="display: none;">true</span> -->
<!-- and --> lines immediately above and below the line you just edited.<!-- and --> lines immediately above and below the <span id="relatedItemsShelf_useGoogleBooks" line./m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/displayRecord.xsl
<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"/>
<xsl:include ... /> statements, insert this new line:
<xsl:include href="./pageFacets/relatedItemsShelfFacets.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.
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/displayStaff.xsl
<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"/>
<xsl:include ... /> statements, insert this new line:
<xsl:include href="./pageFacets/relatedItemsShelfFacets.xsl"/>
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/contentLayout/cl_displayRecord.xsl
<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="'actionBox.recordView.link'"/> </xsl:call-template> <!-- ## Bibliographic Data ## --> <xsl:for-each select="$Config"> <div class="bibliographicData"> <xsl:call-template name="buildMarcDisplay"> <xsl:with-param name="recordType" select="'bib'"/> </xsl:call-template> </div> </xsl:for-each> </div>
</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.)</div> that ends this section, add this new line:
<xsl:call-template name="buildRelatedItemsShelf"/>
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.
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/pageFacets/displayFacets.xsl
</div> </xsl:for-each> </xsl:template> <!-- ###################################################################### --> </xsl:stylesheet>
</div> line, insert the contents of the displayFacets.xsl_additions.txt file.Other browsers not yet supported and the bookshelf will not appear at all.
The bookshelf should appear below the "Holdings Information" section and above the page footer.
Please report any bugs or suggestions about the bookshelf or these instructions.
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!
This section describes OPTIONAL advanced configuration options for the Related Items Bookshelf.
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.
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/pageFacets/relatedItemsShelfFacets.xsl
<xsl:when test="(string-length($callNumber) > 3) and not(contains($callNumber, '/')) and not(contains($callNumber, ':'))">
test expression according to your needs.
contains and not are probably the only necessary functions for most needs.$locationCode variable by uncommenting this line just above the filter expression:
<xsl:variable name="locationCode" select="$HoldXML//*[@name='locationCode']"/>
test expression configuration, designed to filter out certain custom call numbers:
test="(string-length($callNumber) > 3) and not(contains($callNumber, '/')) and not(contains($callNumber, '-')) and not(contains($callNumber, ':')) and not(contains($callNumber, 'ONLINE')) and not(contains($locationCode, 'LOBBY'))"
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.
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.
/m1/voyager/{xxxdb}/tomcat/vwebv/conf/server.xml
<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"/>
name starting with callNumberFilter. (including the period).callNumberFilterNames value, comma-separated, and remove from this value any filter names you wish to disable.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.
/m1/voyager/{xxxdb}/tomcat/vwebv/conf/server.xml
<!-- Filters bookshelf items to match the "headingType" of the primary item. --> <Environment name="useHeadingTypeFilter" value="false" type="java.lang.String" override="false"/>
headingType filter, change the value attribute to true.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:
/m1/voyager/{xxxdb}/tomcat/vwebv/conf/server.xml
<Environment name="adminIpFilter" value="127.0.0.1," type="java.lang.String" override="false"/>
<Environment name="adminIpFilter" value="127.0.0.1,111.222.333.444," type="java.lang.String" override="false"/>
<Environment name="adminIpFilter" value="" type="java.lang.String" override="false"/>
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.
/m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/ui/{skin}/xsl/pageFacets/relatedItemsShelfFacets.xsl
<!-- UNCOMMENT THIS LINE AND CHANGE THE UA NUMBER TO ENABLE GOOGLE ANALYTICS TRACKING <span id="relatedItemsShelf_GA_trackerId" style="display: none;">UA-0000000-1</span> -->
UA-0000000-1 code to match your Google Analytics account number.<span> line remains.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:
toJSONObject.toJSONObject, it is easier to simply override the appropriate field-specific method./m1/voyager/{xxxdb}/tomcat/vwebv/context/vwebv/WEB-INF/classes/
Environment property to server.xml declaring the new class. See the Server.xml Configuration Properties appendix for syntax.Bookshelf administration control is only available from the IP addresses you configured in server.xml.
curl and wget. You invoke administrative actions from the server command line, as in:
$ curl http://localhost/relatedItemsShelf/someAdministrativeActionor
$ wget -O - http://localhost/relatedItemsShelf/someAdministrativeAction
The Related Items Bookshelf application logs key operations to a text file:
/m1/voyager/{xxxdb}/tomcat/vwebv/logs/relatedItemsShelf.0.log
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:
http://{tomcat_server_hostname}/relatedItemsShelf/setLogLevel?level=ALL
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.
Please send bug reports, suggestions, and other feedback to:
Maccabee Levine
Polk Library
University of Wisconsin Oshkosh
levinem@uwosh.edu
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. | 127.0.0.1,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 |