Compass Server 3.0 Developer's Guide

[Contents] [Previous] [Next] [Last]

Chapter 14
Using Java to Access and Modify the Compass Server Database

This chapter discusses how to submit queries and add entries to the Compass Server database using Java.

To do these things, you need to use the Compass Server Java SDK, which is available at:

http://developer.netscape.com/software/sdks/compass/download.html

The Java SDK includes the Java classes needed for interacting with the Compass Server database, Java API documentation, and sample Java files for search and update applications.

The Compass Server Java SDK

The classes in the Compass Server Java SDK provide a Java interface for interacting with the CGI programs for accessing and updating the Compass Server database.

Using the Java SDK, you can build Java applets that submit searches to the Compass Server or add entries to the Compass Server database.

The Compass Server database contains resource descriptions for the indexed resources (such as documents). Each resource description is described in SOIF format, where SOIF stands for Summary Object Interchange.

For a discussion of SOIF format, see:

http://www.w3.org/TR/NOTE-rdm.html#soif.

Downloading and Installing the Compass Server Java SDK

To download the Compass Server Java SDK, point your browser to

http://developer.netscape.com/software/sdks/compass/download.html

Download the appropriate file for your platform and follow the installation instructions on the download page.

Running the Demo Applications

The Compass Server Java SDK comes with a demo directory that contains sample Java files and HTML files.

The SearchPanel.java and the SubmitDemo.java files are ready for compiling and running. You will need to edit the SearchPanel.html and SubmitDemo.html files to pass the information about your Compass Server to the SearchPanel and SubmitDemo applications.

Installing and Running the Search Panel Demo

  1. Compile the SearchPanel.java file. Make sure the class path includes the directory where you installed the Compass Server Java SDK.

  2. Copy or move the resultant SearchPanel.class file to the bin/compass/java/demo directory of your Compass Server installation directory. (If this directory does not already exist, create it.)

  3. Edit the SearchPanel.html file in the demo directory of the Compass Server Java SDK.
The codebase parameter indicates the directory containing the main class and the ancillary classes for the applet. You can specify this in the form:

"http://host_name:compass_server_port/java"

The code parameter indicates the name of the main class file for the applet. In this case, the class file will be in the demo package (subdirectory) of the directory specified by codebase.

For example:

<applet codebase="http://CorporateCompass:80/java"
   code="demo.SearchPanel" width=480 height=75>
The CGILocation param parameter indicates the URL for the Compass Server.

<param name="CGILocation" 
   value="http://host.domain.com:compass_server_port/">
For example:

<param name="CGILocation"
   value="http://www.CorporateCompass.com:80/">

The host param indicates the domain name of the host.

<param name="host" value="host.domain.com">
For example:

<param name="host" value="www.CorporateCompass.com">
The port param indicates the port number for the Compass Server.

<param name="port" value="compass_server_port">
For example:

<param name="port" value="80">
The name param indicates the name of the individual Compass Server instance. (This is a server that you created after starting the Compass Server administration interface.)

<param name="name" value="compass_server_name">
For example

<param name="name" value="guru">
Make these changes, save the file, and move it to wherever you like. When you open it in a web browser, the SearchPanel application should start. Be sure to open the Java console to see the results of submitting a search.

Installing and Running the Submit Demo

  1. Compile the SubmitDemo.java file. Make sure the class path includes the directory where you installed the Compass Server Java SDK.

  2. Copy or move the resultant SubmitDemo.class file to the bin/compass/java/demo directory of your Compass Server installation directory. (If this directory does not already exist, create it.)

  3. Edit the SubmitDemo.html file in the demo directory of the Compass Server Java. Change the param values as appropriate.
This demo adds three resource descriptions to the Compass Database.

Using Java To Access the Compass Server Database

You can use the Compass Server Java SDK to write Java programs that interface with the sendrdm program retrieve information from the Compass Server database.

The main steps are:

  1. Creating a Search Object

  2. Executing A Query

  3. Getting the Results of a Query

Creating a Search Object

The entry point for submitting searches is the Search class. You need to create a new Search object, then call doQuery() or doIncrementalQuery() on it to submit a search query.

The first thing you need to do is create a new Search object. The constructor syntax is:

public Search(
   String scope,
   String viewAttributes,
   String viewOrder,
   int viewHits,
   String queryLanguage,
   CSID csid,
   String CGILocation,
   String CGIName
)
You can omit CGIName, and it defaults to "rdm/incoming".

The arguments for the constructor are:

String scope

The query string or scope, that is, the string being searched for.

String viewAttributes

A comma-delimited list of the SOIF attributes to be retrieved from the database, such as URL, Author, Description. For example:

"score,url,title,description,classification"

String viewOrder

The order by which to sort the attributes. This is a comma-delimited list of attributes. Use the minus sign to indicate descending order, and a plus sign to indicate ascending order. For example:

"-score,+title"

int viewHits

Maximum number of results to return. This value cannot be greater than 1024.

String queryLanguage

The Compass Server query language. You should use "compass" for this value.

CSID csid

This is the Compass Server ID. To get this argument, you can create a new CSID instance, passing it the page's codeBase, the Compass Server domain name, the Compass Server Port, and the Compass Server name.

For example, if your Compass Server host name is http://www.yourcomany.com/, it is installed on port 80, and it has a server instance called guru, you could create a CSID for it as follows:

CSID CS=new CSID(codebase, "http://www.yourcompany.com/", 80, "guru")

A common way to provide the arguments to the constructor for CSID is to pass them as parameters in the <APPLET> tag that invokes the applet.

String CGILocation

The path for the location of the CGI directory of the hosting server, which is needed to access the sendrdm program. This argument has the form:

"http://host.domain.com:compass_server_port/"

For example, if the Compass Server is installed on www.yourcompany.com on port 80, the value would be:

"http://www.yourcompany.com:80/"

A common way to provide this argument is to pass it as a parameter in the <APPLET> tag that invokes the applet.

String CGIName

This is the name of the CGI program that is used to access the Compass Server database. You can usually omit this argument. It defaults to "/rdm/incoming".

Executing A Query

You can submit a query in two ways. The doQuery() function concatenates the query results into one big string buffer. If the string buffer is too big, the query fails. Only use this method when you know that the search results will not be too big. For example, you could use it to get the RD for a specific URL.

You can use the getStringResult() to get the results returned by doQuery() as a string of SOIF items

For larger queries use the doIncrementalQuery() method. This method returns true if there is more data available, and false if all data has been read.

public void doQuery()
public boolean doIncrementalQuery(
   int Increment,
   int ByteLimit)
The average resource descriptor size should be 5K-6K, (assuming you are using the default robot indexing setting of partial text and 4K length). So for 5 results 30K should be a big enough buffer.

Checking The Processing Status

You can use the method Search.getStatus() to get the status of the query process. You can use the method Search.finished() to check if the query process has finished or not.

public final int getStatus()
public final boolean finished()
The following tables shows the possible values returned by getStatus().

Table 1 

Processing Status class variable name value
Processing completed successfully.

COMPLETE

0;

Prepared for processing.

PREPARED

1;

Currently processing.

PROCESSING

2;

Abnormal end -- an error occurred.

ABEND

3;

.

EMPTY

4;

Getting the Results of a Query

The results from Search.doQuery() and Search.doIncrementalQuery() can be obtained using Search.getSOIFResult() or Search.getStringResult(). The next search will overwrite the previous results so you must process them after each query.

public SOIF getSOIFResult()
public String getStringResult()
Search.getSOIFResult() returns -1 if the status is not COMPLETE.

The function Search.resultCount() returns the number of results. The result count is based on being able to count the number of SOIF objects, so if doSOIFParse is false, -1 is returned. (The default for doSOIFParse is true.)

public int resultCount()

Formatting the Results as HTML

You can use the Results class to format the results from Search.doQuery() and Search.doIncrementalQuery() as HTML. The Results class has methods that wrap the search results inside HTML tags.

The method setDisplay() allows you to specify which attributes to display inside HTML tags. These attributes can be a subset of the attributes returned by the search query.

public void setDisplay(String s)
The attributes must be specified as a comma-delimited list, for example:

setDisplay("score", "url", "title", "description", "author");
The method getDisplay() returns a comma-delimited list of the attributes to display inside HTML tags.

public String getDisplay()
The method setDisplayAsLink() specifies which attributes should be displayed as links to the document's URL when the results are formatted as HTML (by invoking the resultsToHTML () method.)

public void setDisplayAsLink(String    s, boolean    b)
For example, if you set both title and url to be displayed as links, then when you HTML-ize the results, both the url and the title for each document will be displayed as links to the document's URL.

setDisplayAsLink("title, true");
setDisplayAsLink("url, true");
The method setScoreGif() associates an image with a range of score values.

public void setScoreGif(int    low,int    high,String    gif)
For example, the following statement associates the image "/images/fourstar.gif" with the score range 80 to 100.

setScoreGif(80, 100, "/images/fourstar.gif")
The function toScoreGifHTML() formats a score returning both percent and image, if any.

public String toScoreGifHTML(String sc)
public String toScoreGifHTML(float sc)
The resultsToHTML() function wraps HTML tags around the results. You can specify the start and end tag for each document and for each SOIF attribute. Alternatively you can specify just the start and end tags for each attribute.

public String resultsToHTML(SOIF soif,String preResult,String    postResult, String preField, String postField)
public String resultsToHTML(SOIF soif, String preField, String    postField)
For example, the following statement specifies that each document is in a table row, and each attribute is in a table cell:

resultsToHTML(search.getSOIFResult(),"<TR>", "</TR>", "<TD>", "</TD>");
The Results class is provided more as an example of a formatting class than as a finished class. You are encouraged to copy the Results class, and modify it to create a report format that suit your needs.

Working Through An Example Search Application

This section discusses the creation of an example application that uses the Java SDK to do a search query. The application that this example builds is similar, but not identical to, the demo search application that is shipped in the demo directory of the Java SDK.

The purpose of this example is to show how to use the Compass Server to submit a query to the database and how to extract the results from the Search object. The example application is very simple, and limits is use of Java to achieving the goals of the example. It creates a Java applet that presents the user with a text field in which to enter a search query, and a "Search" button to initiate the search. The results of the query are saved in a Search object. The query results are displayed in the Java console as straight text and also as HTML-formatted text.

Import the Necessary Files

In your favorite editor or Java development environment, open a file called QueryExample.java. At the top of the file declare this class to be in package demo, and import the necessary classes. The class will use the CSID, Results, SOIF, and Search classes in the soif package. It will use the Applet class in the applet package, and it will use several classes in the awt package. The soif package is provided as part of the Compass Server Java SDK, while applet and awt are standard Java packages.

package demo;
import soif.CSID;
import soif.Results;
import soif.SOIF;
import soif.Search;
import java.applet.Applet;
import java.awt.Button;
import java.awt.Event;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.Color;

Define the QueryExample Class

The class QueryExample is an applet, so it must extend the class Applet.

public class QueryExample extends Applet
Define some variables for use in the class. The variable RETURN represents the ASCII code for the return key on the keyboard. The searchTF variable represents the text field in which the user enters their search query, and searchBtn represents the button that they press to submit the search query. The variable CGIlocation represents the cgi location of the sendrdm.cgi program (which executes queries in the database), and csid represents the specific Compass Server instance ID.

public class QueryExample extends Applet
{
   public final static int RETURN = 10;
   TextField search
   TFButton searchBtn;
   String      CGILocation;
   CSID csid;

Initialize the Applet to Create the Search Form

Define the init() method. The first thing it does is print a brief greeting in the Java console window. (When you run the applet, be sure to open the Java Console to see all the output.)

public void init()
{
   System.out.println("Welcome to the Example Search Application");
The next task is to define the appearance of the applet. Its background will be light blue (or change the color to suit your liking.) The applet needs to have a text entry field where the user enters the search query, and a search button that initiates the search.

/* Set the background to light blue*/
setBackground(new Color(180, 220, 250));
/* Add the text entry field and the search button */
searchBtn = new Button("Search");
searchTF = new TextField("Netscape", 60 );
setLayout(new FlowLayout(FlowLayout.CENTER ) );
add(searchTF);
add(searchBtn);
Before submitting the search, you need to create a Search object. The constructor for the Search class takes several arguments. Two of these arguments are CGILocation and CSID (Compass Server ID.) The init() method of QueryExample is a good place to initialize the CGILocation and CSID arguments, since they do not change for the duration of the applet session.

This applet will be invoked by an <APPLET> tag that has PARAMETER attributes for CGILocation, host, port, and name. You can use these parameters to generate the values for CGILocation and CSID (which have already been declared as instance variables.)

   CGILocation = getParameter("CGILocation");
   csid = new CSID(
      getCodeBase().toString(),
      getParameter("host"),
      getParameter("port"),
      getParameter("name")
   );
/* end of init method */
}

Define the handleEvent() Method

When the user presses the Search button in the form or presses the Return key on the keyboard, the search process is initiated. Thus you need to define a handleEvent() method that checks if the search button was pressed or if the Return key was released while the text field was being edited. If any other event happened, do nothing. If these criteria are met, continue. (The example handleEvent shown here is for Java 1.02.)

public synchronized boolean handleEvent(Event e)
{
   if ((( e.id == Event.KEY_RELEASE)
       && (e.target == searchTF)
       && (e.key == RETURN))
   || (( e.id == Event.ACTION_EVENT)
      && (e.target == searchBtn))
   )
While this method is in progress, make sure the user cannot type in the text field and that nothing else happens if the search button is pressed.

   searchTF.setEditable(false);
   searchBtn.disable();
Next, we need to construct the query to submit to the database. This involves creating a Search object. The arguments for the constructor for the Search class are:

  1. the search string. In this case, we can get the value of the searchTF text field to use as the search criteria.

  2. a comma delimited list of the attributes you want returned (such as description, title, and so on). In this case, we want to get the title, score, rule, and description of all documents that match the query.

  3. a comma delimited list of the attributes to be used to sort the results. A minus sign indicates descending order, a plus sign indicates ascending order. In this case, sort the results by decreasing numerical score value, and use alphabetical order of the title as the secondary sort order.

  4. the maximum number of results to return.(This value cannot be more than 1024.)

  5. the Compass Server query language, which you can specify as "compass".

  6. CSID (Compass Server ID) instance. In this case, we have already defined the variable csid to represent the Compass Server ID.

  7. path to the cgi directory for sendrdm. In this case, we have already defined the variable CGILocation for this purpose.
    Search search = new Search(
       searchTF.getText(),
       "title,description,score,url",
       "-score,+title",
       10,
       "compass",
       csid,
       CGILocation
    );
Having created the Search object, use it to submit the query.

search.doQuery();
The results are stored in the Search object. Now do something with the results. The functions doSomethingWithResults() and displayHTMLResults() will be defined in this file. They each show a different way of extracting the results from the Search object.

   doSomethingWithResults(search);
   displayHTMLResults (search);
Switch the text field and the search button back on. Return true and end the conditional case for handling the search submission.

   searchTF.setEditable(true);
   searchBtn.enable();
   return true;
}
Be sure to return super.handleEvent() if the user did not submit a query to ensure that when the user types in the text field, the text entry events are handled correctly.

return super.handleEvent (e);
/* end of handleEvent */
}

Show the Results in the Java Console

The example application includes a simple function that displays the query results in the Java console window. In reality, you would do more with the results than just print them to the console window, but once you know how to get the results out of the Search object, it is up to you what you do with them. You can use standard Java functionality to process the results in any way you like.

The class Search has a method getSOIFResult() that returns a SOIF object representing a single result. Each SOIF object has a next instance variable that points to the next result, if there is another one. You can use the getValue() method of a SOIF object to get the value of a particular field, for example, getValue("title") gets the title of a SOIF object.

The example function doSomethingWithResults() first prints the total number of results, then gets each result in turn as a SOIF object, then prints its url, title, description, and score in the Java console window.

public void doSomethingWithResults(Search search)
{
/* Get a result count. -1 indicates an error, 
** which can also be discovered by using search.getStatus().
*/
System.out.println(
   "number of hits: ["
   + search.resultCount()
   + "]"
);
/* Examine the results of the search. The following
** block loops through a list of SOIF instances.
*/
for (SOIF soif = search.getSOIFResult();
   soif != null;
   soif = soif.next
)
{
/* use the getValue() method to get a value associated
** with the specified attribute.
*/
String u = soif.getValue("url");
String t = soif.getValue("title");
String d = soif.getValue("description");
String sc = soif.getValue("score");
/* Print the results. */
System.out.println(
   "TITLE: " + t +
   "\nURL: " + u +
   "\nSCORE: " + sc +
   "\nDESCRIPTION: " + d +
   "\n----------------------------------\n\n"
   );
}
}

Displaying the Results in HTML Format

The example displayHTMLResults() displays the results as HTML-formatted text. This function uses the pre-defined resultsToHTML() function of the Results class. In this case, each resulting document is wrapped in the HTML tags for a table row, while each field within the document is wrapped in the HTML tags for a table cell.

This function sends the HTML-formatted results to the Java console. In practice, you would most likely want to extend this function (using standard Java code) to send the results to a web page.

public void displayHTMLResults (Search search) {
   /* Use a Results object to format the results in HTML */
   Results results = new Results();
   results.setDisplay("title,description,score,url");
   results.setDisplayAsLink("title", true);
   results.setScoreGif( 0, 50, "okmatch.gif");
   results.setScoreGif(51, 100, "goodmatch.gif");
   System.out.println("Here comes the HTML-formatted text...");
   System.out.println("");
   System.out.println(
   results.resultsToHTML(
   search.getSOIFResult(),
      "<tr>\n",
      "</tr>\n\n",
      "<td>\n",
      "\n</td>\n"
      )
   );
}
/* End the class */
}
For the complete code for the class file, see QueryExample.java.

Creating the HTML File to Display the Applet

After you've compiled the QueryExample.java file, copy the resulting class file to the bin/compass/java/demo directory of your Compass Server installation directory.

Next, you need to define the HTML file to display the applet, as shown below. (You can use whatever colors you like for the text, bgcolor, vlink, link, and alink parameters of the body tag.)

<html>
<head>
<title>Search Query Example</title>
</head>
<body text="#0000FF" bgcolor="#FFFFFF" 
   vlink="#B8860B" link="#F8C64B" alink="#D3D3D3">
<h1>Search Panel Example</h1>
<p><center>
<applet codebase="http://yourCompassServerName:Port#/java"
   code="demo.QueryExample"
   width=480 height=75 align=left>
<param name="CGILocation" value="http://CompassServerName:Port#/">
<param name="host" value="CompassServerName">
<param name="port" value="port#">
<param name="name" value="CompassServerInstanceName">
This interface requires a Java aware browser.
</applet>
</center>
<BR CLEAR=ALL>
<p><BR>
<P>Note: Search results are sent to the Java console.</p>
</body>
</html>
The <APPLET> tag has parameters for CGILocation, host, port, and name, since these values need to be passed to the Java class. The host is the Compass Server name, whereas name is the name of the Compass Server instance (which you created after starting the Compass Server administration interface.). For example, if you installed the Compass Server at www.CompassName.com on port 80, and created a server instance called guru, then the <APPLET> tag would be:

<applet codebase="http://CompassName:80/java" 
   code="demo.QueryExample" width=480 height=75 align=left>
   <param name="CGILocation"
      value="http://www.CompassName.com:80/">
   <param name="host" value="www.CompassName.com">
   <param name="port" value="80">
   <param name="name" value="guru">
This interface requires a Java aware browser.
</applet>

Using Java To Add Entries to the Compass Server Database

The communications package in the Compass Server Java SDK contains classes for communicating with the Compass Server database. These classes connect to the database through a CGI program, rdsubmit. You can use these classes to import data in SOIF format into the Compass Server database. You can import new RDs into the database, or modify existing ones.

The basic process for adding entries to the database is to convert the input to SOIF and then add it to the database using rdsubmit.

To add entries to the database, convert the input to SOIF format, then pass the input to the doWrite() method of the PostConnection class. The dowrite() method invokes the rdsubmit program to submit the data.

PostConnection.doWrite()

Use the doWrite() method of the PostConnection class in the communications package to write data to the Compass Server database.

The signature is:

public static String doWrite(
   String CGIlocation,
   String rdm-message,
   boolean b
)
The arguments are:

String CGIlocation

The URL to the rdsubmit program on the Compass Server instance. For example:

      "http://guynt:11000/compass-compassjan/bin/rdsubmit"
String rdm-message

This argument is an RDM in SOIF format to be submitted to the Compass Server database. See section More Details on the rdm-message Argument for more information about this argument.

Boolean b

This argument specifies whether or not to return the string result. If the value is false, then doWrite() returns a null string. If the value is true, the result string is returned. The result string is in the form of a SOIF string and is the result the server generated in response to the submission.

More Details on the rdm-message Argument
The PostConnection.doWrite() method submits a resource description message (RDM). RDM messages must be in SOIF format. Each RDM must have a header and a body. The header contains information about the kind of message, where it needs to go, and what it needs to do. The body contains the data for the message. For more information about RDM and SOIF formats, see:

http://www.w3.org/TR/NOTE-rdm.html

The second argument for PostConnection.doWrite() must be an RDM. In this specific case, we need an RDM whose header is of type @request, (since we are making a request), and whose body is of type document (since we are sending a document to be submitted to the Compass Server database.)

A SOIF object consists of a schema name (such as @request or @document), a URL, and a list of attribute-value pairs. The soif package in the Compass Server Java SDK contains a class AVPairs that has a class method toSoif(). This method takes an attribute name and value and generates an attribute-value pair in SOIF format. For example:

AVPairs.toSoif("title", "All about SOIF");
generates a result something like:

title{20}: All about SOIF
You can use the AVPairs.toSOIF() method to help create an RDM in SOIF format.

Here is an example of constructing an RDM that can be used as the second argument to PostConnection.doWrite().

First, create a string buffer:

StringBuffer sb = new StringBuffer();
Write the header part of the RDM to send to the database. SOIF objects of type @Request do not have an associated URL.

sb.append("@REQUEST { -\n");
An RDM that is requesting an update to a Compass Server has the following attribute-value pairs:

submit-csid

submit-type

submit-operation

submit-view

Write attribute-value pairs for each of these attributes to the string buffer:

sb.append(AVPairs.toSOIF("submit-csid", x-catalog://nikki.boots.com:80/compass1
+ AVPairs.toSOIF("submit-type", "persistent")
+ AVPairs.toSOIF("submit-operation", "merge")
+ AVPairs.toSOIF("submit-view", "title,author,description")
+ "}\n");
Write the body part of the RDM. We'll be sending a resource description for a document, whose URL is "http://www.best.com/~jocelyn/resdogs.index.htm", whose title is "Saving English Springer Spaniels," whose author is Jocelyn Becker, and whose description is "English Springer Spaniels in need of homes."

sb.append("\n@DOCUMENT{\n" 
+ "http://www.best.com/~jocelyn/resdogs.index.htm\n"
+ AVPairs.toSOIF("title", "Saving English Springer Spaniels")
+ AVPairs.toSOIF("author", "Jocelyn Becker")
+ AVPairs.toSOIF("description", "English Springer Spaniels in need of homes")
+ "}"
The string buffer now contains the following RDM in SOIF format:

@REQUEST { -/
  submit-csid{20}: x-catalog://nikki.boots.com:80/compass1
  submit-type{23}: persistent
  submit-operation{29}: merge
  submit-view{30}: title,author,description
}
@DOCUMENT { http://www.best.com/~jocelyn/resdogs/index.html
  title{35}: Saving English Springer Spaniels
  author{37}: Jocelyn Becker
  description{39}: English Springer Spaniels in need of homes
}
You can convert the string buffer to a string, and use it as the second argument for PostConnection.doWrite(). For example, the following statement writes the new resource description to the Compass Server database:

result = PostConnection.doWrite(CGILocation, sb.toString(),true);

Example

See the SubmitDemo.java class file and SubmitDemo.html HTML file in the demo directory of the Java SDK for an example.


[Contents] [Previous] [Next] [Last]

Last Updated: 02/07/98 20:49:24

Any sample code included above is provided for your use on an "AS IS" basis, under the Netscape License Agreement - Terms of Use