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

Reply via email to