| Previous | Table of Contents | Next |
Servlets are a powerful mechanism for serving dynamic Web pages. They have begun to fill an important role in Java client/server programming. Many developers are creating applet/servlet pairs that cooperate to form a complete application. Applications are often split for reasons that include improving performance, minimizing network traffic, and centralizing business logic. The decision to use servlets and applets is often one of portability and accessibility. Applets run on most browsers, making them a portable client choice. Servlets run as part of the Web server, making them accessible via HTTP through most corporate firewall configurations. By splitting a program into this type of pair, the programmer is basically guaranteed that anyone can run an application.
Connecting an applet to a servlet is really more of an applet programming problem than a servlet one. The applet can use standard HTTP to communicate with the servlet, so the servlet doesnt need to do anything special. However, for servlets that are designed to talk to an applet, the servlet can optimize its communication by return text or binary data instead of HTML. The following example implements the classic Eliza computer psychologist as an applet/servlet pair. The applet displays a user interface, and the servlet performs all of Elizas processing. The engine for Eliza is provided in a special package, augmented slightly from the public domain package written by Charles Hayden. (Thanks, Charles!)
As you can see from the servlet code that follows, both GET and POST requests are handled, and the Eliza engine is used to handle the incoming message. Plain text is returned to minimize the applets job in interpreting it. The DebugLog object, discussed in the section Debugging Servlets, is also used. This servlet has two init parameters for debugging and one for defining the script file Eliza uses. This script file is provided on the CD-ROM with the other files in the Eliza package and can be edited to respond differently.
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import Eliza.*;
public class ElizaServlet extends HttpServlet
implements SingleThreadModel
{
ElizaMain eliza;
DebugLog logger;
The initialization for this servlet prepares the DebugLog (discussed later) and loads the Eliza engine based on the configured script file.
public void init(ServletConfig conf) throws ServletException
{
super.init(conf);
String logFile,logServer,scriptFile;
int res;
logFile = getInitParameter(logfile);
logServer = getInitParameter(logserver);
scriptFile = getInitParameter(scriptfile);
eliza = new ElizaMain();
if((logFile != null)||(logServer != null))
{
logger = DebugLog.getSharedLog();
synchronized(logger)
{
if(!logger.initialized())
{
if(logServer != null)
{
logger.logTo(logServer);
}
else
{
logger.logTo(new File(logFile));
}
}
}
}
try
{
res = eliza.readScript(scriptFile);
eliza.setLog(logger);
}
catch(Exception exp)
{
res = -1;
logger.log(exp);
}
if(res != 0) logger.log(Couldnt create eliza main.);
}
When a GET or POST request is received, the servlet calls its internal respondToMessage method to handle the request.
public void doGet(HttpServletRequest request,
HttpServletResponse response)
{
String message;
message = request.getParameter(message);
respondToMessage(message,response);
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
{
String message;
message = request.getParameter(message);
respondToMessage(message,response);
}
The respondToMessage method checks if a message was entered. If no message was sent then a welcome reply is returned. If a message was sent, Eliza is queried. If Eliza is unavailable, an apology is returned to the user. All responses are simply text messages.
protected void respondToMessage(String message
,HttpServletResponse response)
{
PrintWriter out=null;
String reply;
try
{
if(message==null)
{
reply = Please enter a message to Eliza.;
}
else if(eliza != null)
{
reply = eliza.processInput(message);
}
else
{
reply = Sorry, Eliza is not available.;
}
}
catch(Exception exp)
{
reply = I am having trouble hearing,
+please repeat.;
logger.log(exp);
}
try
{
response.setContentType(text/plain);
out = response.getWriter();
out.println(reply);
}
catch(Exception exp)
{
}
finally
{
if(out != null) out.close();
}
}
public void destroy()
{
logger.closeLog();
}
}
The applet for Eliza creates a simple user interface and responds to action events from the text field. This applet is pictured in Figure 7.7. It is certainly not pretty, but it provides the necessary code to demonstrate applet servlet messaging. Standard JDK 1.0 event handling is used to maximize portability, although the applet has been tested only on Netscape Navigator 3.0 and 4.0.
The majority of the applet/servlet code is in the action method. In the following code, the applet checks whether the parameters say to use GET or POST to talk to the servlet. If POST is used, the applet creates a URLConnection; otherwise, a URL with a query string is used to connect to the servlet. POST messages require the connection to support output, in this case a URL-encoded key-value pair containing the users message to Eliza. Notice the one piece of code changing the content type. This is required to get the applet to work in Netscape. Once the message is posted to the servlet, the applet reads the response as plain text and displays it in a label.
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;
public class ElizaApplet extends Applet
{
Label response;
TextField request;
String server;
public void init()
{
Font f = new Font(Times-Roman,Font.PLAIN,16);
Label message;
response = new Label(Eliza will see you know.);
response.setFont(f);
request = new TextField(24);
request.setFont(f);
setLayout(new GridLayout(2,1,5,5));
add(response);
add(request);
try
{
server = getParameter(server);
}
catch(Exception exp)
{
server = null;
}
}
public boolean action(Event evt,
Object what)
{
if(evt.target == request)
{
String reply;
String message;
DataInputStream reader;
InputStream in=null;
URL url;
try
{
message = message=;
message += URLEncoder.encode(request.getText());
if(POST.equals(getParameter(method)))
{
URLConnection connection;
PrintStream printOut;
url = new URL(server);
connection = url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
//Work around for netscape settings for
//post requests.
connection.setRequestProperty(Content-Type
, application/x-www-form-urlencoded);
printOut=new
PrintStream(connection.getOutputStream());
printOut.print(message);
printOut.flush();
printOut.close();
in = connection.getInputStream();
}
else
{
url = new URL(server+?+message);
in = url.openStream();
}
reader = new DataInputStream(in);
reply = reader.readLine();
reader.close();
in.close();
}
catch(Exception exp)
{
reply = Error, network may be down.; }
response.setText(reply);
request.selectAll();
}
return true;
}
}
Figure 7.7 The Eliza applet.
Notice that the applet uses regular HTTP requests to talk to the server and simply reads the results in the expected format. In this case, the results are a text string, but the servlet could return an image, file, or other resourceeven a serialized object. In other words, although the applet/servlet relationship is affected by the performance of HTTP and intervening firewalls, it is a very flexible mechanism for distributed computing. Even this techniques reliance on HTTP makes it portable across most installations.
| Previous | Table of Contents | Next |