The available target search services in the Support Assistant Search feature are not fixed. They are configured into the feature through configuration file specifications. This document describes the supported method of configuring additional target search services into the Search feature.
There are two supported scenarios for search target extensibility.
• New instance
The simplest scenario involves an additional target that is similar to an existing target. As shipped, the Support Assistant knows how to search an eclipse help server. In order to configure the Search feature for a new eclipse help server, one simply drops in a new search service configuration file.
• Canonical message format
A specific scenario of interest is that where an organization has its own internal document repository and is looking to hook its own search service into the Search feature.
In general, integration with a new kind of target search service requires some coding to adapt between the search model used by this new target and the search model used by the Search feature. The strategy provided for here involves coding at the server to implement an HTTP request interface (with an XML response content) specified by the Search feature.
Support Assistant is deployed as a component of multiple product platforms. This document addresses extensibility for Support Assistant on the eclipse product platform.
A “contributor” in these use cases is the person that is updating the eSupport Client for Search Target extensibility
As noted above, the only thing required here is the addition of a search service configuration file.
The Support Assistant is a J2EE web application. The search target configuration files are installed under the web application “document root”. On the eclipse platform, this root directory is the plugin directory for the following eclipse plugin.
com.ibm.esupport.client.webapp
The location for search service configuration files, relative to this root directory, is:
/search/conf/services
A service configuration file is an XML document that conforms to the following XML schema.
/search/conf/schema/service-cfg.xsd
Each configured search target must have a unique internal ID. This ID is specified within the configuration file. By convention, this ID is used as a filename prefix for the configuration file.
<sid>-cfg.xml
The configuration file includes specification of label strings to use in the Search feature user interface. National Language support (NLS) for these label strings is enabled through the use of resource files. These NLS resource files are placed in the following directory.
/search/conf/services/resources
The resource file names must conform to the following pattern.
<sid>-labels[_lc[_cc[_vc]]].properties
The use of locale in encoding the filename is consistent with that used by Java ResourceBundles. A German label strings resource file for the “acme” search service, for example would be named as follows.
acme-labels_de.properties
This scenario can be understood as an extension of the “new instance” scenario. Everything noted above for that scenario applies equally here. In addition, this scenario requires server side coding to implement the search request protocol.
The essential features of the search request protocol are described below.
The configuration file for this scenario must specify the following proxyClassName.
com.ibm.esupport.client.search.proxy.canonical.CanonicalSearchRobot
The configuration file must also specify a serviceURL - an HTTP URL such as the example below.
http://w3.acme.com/search?parm1=value1
Note that any number of static service specific parameters may be included in the URL specification (e.g., “parm1=value1”). If the target search service provides for document classification, then the configuration file should include a sequence of documentCategory.
HTTP is the supported transport protocol. UTF-8 is the supported character encoding.
The configured serviceURL will be completed by the addition of the following request parameters.
query – The string entered by the user
count – The maximum number of results to return
cat – (optional) A document category identifier
Document category is an aspect of the search model than can be exploited if the target search service provides for meaningful document classification. When document categories are used, the following should hold.
A cat parameter is interpreted as a Boolean AND operand. That is:
query=foo AND cat=bar
Multiple occurrences of the cat parameter are supported. In this case, multiple categories are interpreted as an inclusive OR. That is:
query=foo AND (cat=bar1 OR cat=bar2)
The HTTP response body is an XML document conforming to the following DTD.
/search/conf/schema/canonical_results.dtd
A “hit” is represented as a “Docref” element, a “web document reference”.
<!ELEMENT Docref (Title,Url,Description?)>
Docrefs are aggregated by document category into “SearchResult” elements. Within a SearchResult, the ordering of Docrefs is understood to be “rank order”.
SearchResults are aggregated into a “SearchResultSet” element, the root element of the response document.
The principal dimension of variation in this protocol is the presence of document categories.
If the search service does not support document categories, document categories should be omitted from the service adapter configuration. A “no categories” service should always return a SearchResultSet having one SearchResult with a “documentCategory” attribute of “DEFAULT”.
When document categories are specified in the service adapter configuration, they are enabled for selection by the user. The user may select zero or more categories. If a user selects zero categories, they are indicating “any category” and there will be no “cat” parameters passed in the request.
In response to a request specifying one or more categories, the user will typically expect the results to also be categorized, therefore, the search service should respond with a result set which includes a SearchResult for each category. If the SearchResult attribute “documentCategory” matches a category ‘id’ value as specified in the service configuration, then the displayed value will be the corresponding ‘name’ value in the service configuration. The “hitcount” attribute should indicate number of hits within the category. (Note that this generally will be greater than the number of Docrefs in the returned SearchResult).
A SearchResult hitcount of zero is used to indicate “no hits” within a category.
In response to an “any category” request, the search service may return a result set containing one or more SearchResults. That is, the results may be either categorized (if possible) or uncategorized. Categorized results are always to be preferred.
package com.mycompany.canonicalsearch; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Sample SearchAdapterServlet for implementing a new * Canonical Message Format search service for IBM Support Assistant */ public class SearchAdapterServlet extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // get the query string String query = req.getParameter("query"); // get the max number of results to return int maxResults = Integer.parseInt(req.getParameter("count")); // get any categories that were passed String[] cats = req.getParameterValues("cat"); // optionally, get the encoding in case our results can be translated String enc = req.getLocale(); /* * Do some magic here to invoke your search service using the parameters * passed in the request. */ MySearchService searchService = new MySearchService(); searchService.setQueryTerm(query); searchService.setMaxResults(maxResults); searchService.setCategories(cats); searchService.setEncoding(enc); MySearchResponse returnedObject = searchService.invokeSearch(); /* * Do some more magic here to process the returned object into the * expected HTTP response XML document */ PrintWriter writer = resp.getWriter(); writer.write(marshalResultsToXML(returnedObject)); writer.flush(); } /* * This method takes the object returned from invoking MySearchService * and marshals it into the XML format expected by the IBM Support Assistant * CanonicalSearchRobot */ private String marshalResultsToXML(MySearchResponse returnedObject) { StringBuffer sb = new StringBuffer(); sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); sb.append( "<SearchResultSet hitCount='" + returnedObject.getTotalHits() + "'>"); MySearchResultCategory[] cats = returnedObject.getCategories(); for (int i = 0; i < cats.length; i++) { sb.append( "<SearchResult documentCategory='" + cats[i].getCatName() + "'hitCount='" + cats[i].getCatHits() + "'>"); MyCategoryResults[] catResults = cats[i].getCatResults(); for (int j = 0; j < catResults.length; j++) { sb.append("<Docref>"); sb.append("<Title>" + catResults.getTitle() + "</Title>"); sb.append("<Url>" + catResults.getUrl() + "<Url>"); sb.append( "<Description>" + catResults.getDescription() + "<Description>"); sb.append("<Docref>"); } sb.append("<SearchResult>"); } sb.append("<SearchResultSet>"); return sb.toString(); } }