Writing Java Servlets
Java servlets are Java programs designed to be executed by a Web server and are normally invoked through a URL. This section discusses how you can write and use Java servlets with Domino. In this section we'll explore a Java servlet named Books, which illustrates how to use a servlet to display a list of books stored in a Domino database. By design, it's very similar to the preceding Java application so that you can compare and contrast the two techniques.
Like all servlets, Books is invoked by a browser through a URL. It takes one parameter via the query string that's used to determine whether all the books will be shown, or only those that match the specified search parameter. Figure 19.2 shows the output of the Books servlet.
Figure 19.2. The output from the Books servlet.
Understanding Servlets
To run servlets, you need a Web server and servlet engine. Domino has both, but it's often a good idea to use CORBA to connect to Domino from an external Web server (such as Apache), which is running with a separate servlet engine, (such as JRun or IBM's WebSphere).
Servlets themselves are pretty easy to understand. To kick things off, point your browser to a Web address like the following:
http://www.libertastechnologies.com:81/servlet/ContactInformation
This request gets sent to the Web server at www.libertastechnologies.com , which recognizes the /servlet/ path in the URL and sends the request off to its servlet engine. If Books hasn't previously been loaded, the servlet engine loads it and then calls the servlet's init() method to do some initialization. The servlet engine then creates a request object that contains the context and parameters of the browser request. It also creates a response object, which is used later to generate the result and send it back to the browser.
Both objects are then passed to the service() method, which determines whether it's a GET request or a POST request. The main difference is that GET requests pass query string parameters through the URL in the format name = value , where name is the name of the parameter and value is the value of the parameter. Query string parameters are appended to a URL following a question mark ( ? ) and multiple parameters are delimited with an ampersand ( & ). For example:
http://www.libertastechnologies.com/page.asp?branch=company&page=books
In contrast, data sent to a Web server using the POST method is passed through the document header and is hidden from view. When the service() method has determined the type, the request and response objects are passed to either the doGet() method or the doPost() method. Most servlets use one or the other as their main processing routine for generating response pages.
Because each request is handled in its own thread, you have to be careful with shared member fields. Servlet engines can handle dozens of requests at a time. Serious problems can occur if one thread causes a change to a shared object while another thread is still using it. Most Domino objects are thread-safe, meaning separate threads won't step on each other's toes, but other fields must be declared with the synchronized modifier. The following code snippet illustrates this concept:
public synchronized Item nitmName;
This declaration ensures that only one thread can use mItem at a time. You can also declare methods synchronized, but this can seriously affect performance, particularly in a servlet, so take such an approach cautiously and do it only if you really know what you're doing. In most cases, the best bet is to stick to local variables because they're always unique to each thread.
Using Servlets in Domino
To use servlets in Domino, you must first ensure that the HTTP task is running on your Domino server. If you can access the server with a browser, HTTP must be running. If not, you can type the following at the server console:
Load HTTP
This launches the HTTP server task. Keep in mind that the next time you restart the server, you'll have to do this again. To make the HTTP server task start automatically each time the server is started, open the notes.ini file on the Domino server and add HTTP to the ServerTasks variable. For example:
ServerTasks=Update,Replica,Router,AMgr,AdminP,HTTP,LDAP
When the HTTP task is running and serving pages, you need to enable the Domino Servlet Manager by changing the Java Servlet Support option in your Server document (see Figure 19.3).
Figure 19.3. To use servlets in Domino, you must enable Java Servlet Support in the Server document in the Internet Protocols and Domino Web Engine tabs.
Next, create a subdirectory called servlet in your server's datadomino directory. This is the base directory for all servlet files.
For security reasons, Domino won't allow fully qualified class names. Instead, you must create a text file called servlets.properties in the data directory. This file can define any number of servlet aliases that map short names to their corresponding full class names . For example:
servlet.Books.code=com.pearson..book.Books
This definition maps the alias Books to com.pearson.book.Books . You can then run the servlet as shown here:
http://www.libertastechnologies.com:81/servlet/Books
The Domino server uses the alias in the servlets.properties file to find the class file. Additionally, you can also use the servlets.properties file to define initialization parameters, which can be used in the init() method when the servlet is first loaded.
Listing 19.2 is for a servlet that takes a single query string parameter and searches a Domino database for a list of matching books. All output from the servlet is sent back to the browser as HTML.
Listing 19.2 Books Servlet Source Code
import lotus.domino.*; import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class Books extends HttpServlet { // message constants static final String NOTES_EXCEPTION_MSG = "Notes Exception "; static final String SERVLET_TITLE = "Dave's Favorite Books"; static final String BOOK_TITLE = "Notes and Domino Development Unleashed"; static final String COPYRIGHT_MSG = "(c) 2002 by Pearson "; // field names static final String AUTHOR_ITEM = "Author"; static final String TITLE_ITEM = "Title"; static final String PUBDATE_ITEM = "PubDate"; // parameter name constants static final String QUERY = "query"; // web page constants static final String COLUMN1_LABEL = "Author"; static final String COLUMN2_LABEL = "Title"; static final String COLUMN3_LABEL = "Date"; // application constants static final String BOOKS_DB_NAME = "FileLibrary.NSF"; static final String VIEW_NAME ="Books"; public String getServletInfo() { return SERVLET_TITLE + " - " + BOOK_TITLE + " " + COPYRIGHT_MSG; } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { // make session and database local variables because of multi-threading Session nsCurrent; Database ndbBooks; View nvwBooks; DocumentCollection ndcBooks; Document ndocBook; // set MIME content type to HTML and acquire output stream for response response.setContentType( "text/html" ); ServletOutputStream sosOutput =response.getOutputStream(); try { NotesThread.sinitThread(); long lngCount=0; nsCurrent = NotesFactory.createSession(); ndbBooks = nsCurrent.getDatabase( nsCurrent.getServerName(), BOOKS_DB_NAME ); nvwBooks = ndbBooks.getView(VIEW_NAME); sosOutput.println("
" + SERVLET_TITLE+ "