I've had some good success doing Object communication between an
Applet and Servlet. The limiting factor I found was that the browser
(Netscape 4.5 in my case) would loose the Input and Output Streams
in an unpredictable manner. I found that if I limited my reads and writes
to one object that it worked every time. In order to allow multiple Objects
to be passed between the Applet and Servlet, I wrap all of the Objects
in a Hashtable which becomes the one object that is passed between
the two.
This is a snippet of the Applet and Servlet code. I would be interested
in any comments/suggestions for improvement.
Applet: The applet sends a command along with parameters that should
be invoked by the servlet.
/**
* Send the command to the servlet. This method is synchronized to
* ensure that the entire send and reply are completed before another
* thread attempts to send a command.
* @return java.lang.Object
* @param command the name of the method to be called by the servlet
* @param params parameter list
*/
protected synchronized Object sendCommand(String command, Hashtable params) {
ObjectInputStream inputStream = null;
ObjectOutputStream outputStream = null;
Object result = null;
try {
// Create the URL and establish a connection to the web server.
servletURL = new URL(getUrlString());
// Create the parameter list.
if (params != null) {
setParamList(params);
} else {
setParamList(new Hashtable());
}
// Add the command to the parameter list.
getParamList().put("command", command);
// Open the connection to the servlet URL
URLConnection conn = servletURL.openConnection();
// Prepare for both input and output
conn.setDoInput(true);
conn.setDoOutput(true);
// Turn off caching
conn.setUseCaches(false);
outputStream = new ObjectOutputStream(conn.getOutputStream());
// Send the command on the input stream
if (outputStream != null) {
outputStream.writeObject(getParamList());
} else {
throw new Exception("Could not get the output stream from the connection.");
}
// Create the input stream that the commands will use to read the
// values returned from the transaction.
inputStream = new ObjectInputStream(conn.getInputStream());
Hashtable h = (Hashtable)inputStream.readObject();
int rc = ((Integer)h.get("rc")).intValue();;
result = h.get("rv");
} catch (Exception e) {
System.err.println("ERROR sendCommand: " + e.getClass().getName() +
e.getMessage());
}
return result;
}
Servlet: The servlet matches the command with a method, invokes it and
returns the result to the applet.
public void service (HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
ObjectOutputStream outputStream = null;
ObjectInputStream inputStream;
String command = null;
int rc = 0;
Object returnValue = null;
try {
// Get the parameter list from the input stream.
inputStream = new ObjectInputStream(req.getInputStream());
setParamList((Hashtable)inputStream.readObject());
if (getParamList() == null) {
throw new Exception("A parameter list was not found on the request input
stream.");
}
// Get the command from the parameter list.
if (getParamList().containsKey("command")) {
command = ((String)getParamList().get("command")).trim();
getParamList().remove("command");
} else {
throw new Exception("A command was not specified in the parameter list.");
}
// Use reflection to determine if this is a valid method. If
// so, invoke the method. One limitation of this approach is that
// the parameter portion of the method signature is not known so
// proxy methods may have to be set up to forward the request to
// the appropriate method. The alternative to this is a big
// if-else if control structure that directly calls the proper
// method.
Method method = this.getClass().getMethod(command, null);
if (method == null) {
throw new Exception("The method " + command + " was not found in class " +
this.getClass().getName());
}
returnValue = method.invoke(this, null);
// If the return value for the method was void or the method returned
// null, set it to a string to be sent back to the client.
if (returnValue == null) {
returnValue = new String("No return value");
}
} catch (Exception e) {
// Signify an error and return the exception to the applet.
rc = -1;
returnValue = e;
}
// Use the response output stream to create an ObjectOutputStream
// to be used by the commands to send the client response.
outputStream = new ObjectOutputStream(res.getOutputStream());
// Set the content type of the response so it won't be interpreted by
// the browser.
res.setContentType("application/data");
// Send the return code and the return value as elements of a Hashtable.
// This allows both values to be sent back with one write operation.
Hashtable h = new Hashtable(2);
h.put("rc", new Integer(rc));
h.put("rv", returnValue);
outputStream.writeObject(h);
// Since connections are not persistent, the output stream has
// to be closed at the end of each service request.
outputStream.close();
}
Chris Wolfe wrote:
> It should be easiest with an ObjectOutputStream (around the
> Response.getOutputStream), and an ObjectInputStream on the Applet end of
> the URLConnection.
>
> On the other hand, you may want to avoid this. I have heard some horror
> stories about the incompatible classes in the various browser JVMs. The
> safest way is still to dump the great gobs of primitive + String data
> over the connection :)
>
> You *may* be able to get away with it if you cut your own Serializable
> data-carrier class, though I have never tried it to see if it will work
> any better. I just created my own version of Externalizable
> (Transferable), and have been using TransferableInput/OutputStreams ever
> since.
>
> Cheers,
> Chris
>
> Mark wrote:
> >
> > For all that have helped in the past, I THANK YOU.
> >
> > I have one more question. In passing objects from a Servlet to an Applet,
> > where can I find the type of objects that can be passed. Supposedly Servlets
> > are better than CGI because of this particular reason, that Servlets and
> > Applets are created with JAVA and communication between them would be much
> > smoother. I successfully sent a String value but nothing else. Would like to
> > send a whole ResultSet containing one record from the servlet to the applet.
> >
> > Any help would be of great assistance to me.
> >
> > Thank you,
> >
> > Marco A. Osuna
> >
> > ___________________________________________________________________________
> > To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
> > of the message "signoff SERVLET-INTEREST".
> >
> > Archives: http://archives.java.sun.com/archives/servlet-interest.html
> > Resources: http://java.sun.com/products/servlet/external-resources.html
> > LISTSERV Help: http://www.lsoft.com/manuals/user/user.html
>
> ___________________________________________________________________________
> To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
> of the message "signoff SERVLET-INTEREST".
>
> Archives: http://archives.java.sun.com/archives/servlet-interest.html
> Resources: http://java.sun.com/products/servlet/external-resources.html
> LISTSERV Help: http://www.lsoft.com/manuals/user/user.html
___________________________________________________________________________
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff SERVLET-INTEREST".
Archives: http://archives.java.sun.com/archives/servlet-interest.html
Resources: http://java.sun.com/products/servlet/external-resources.html
LISTSERV Help: http://www.lsoft.com/manuals/user/user.html