Servlet and RMI Callback

Discussions

Web tier: servlets, JSP, Web frameworks: Servlet and RMI Callback

  1. Servlet and RMI Callback (3 messages)

    If anybody could help me with the following it would be very much appreciated.

    What I am trying to do is invoke a servlet that sends a request through RMI. The remote method is called from doGet(). The servlet also exports itself so that the remote object can callback to a method in the servlet to write out the result to the invoking browser. I have tried saving the PrintWriter output stream in the doGet() method and then using this from the called back function. It doesn't work.

    Has anybody got any ideas.

    The following is an idea of what I'm trying to do.

    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.rmi.*;
    import java.rmi.server.*;

    public class xxxxRequestServlet extends xxxxServlet implements xxxxResponse {
       HttpServletRequest request = null;
       HttpServletResponse response = null;
       PrintWriter out = null;

       public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
          this.request = req;
          this.response = res;
          
          System.out.println("Generating request");

          response.setContentType("text/html");
          out = response.getWriter();

          try {
             UnicastRemoteObject.exportObject(this);
          }
          catch(Exception ex) {
             System.out.println("Exception: doGet - exportObject");
             ex.printStackTrace();
          }

          try {
             fnr.generateRequest(this, "GetLibraries", "");
          }
          catch (Exception ex) {
             System.out.println("Exception: doGet - generateRequest");
             ex.printStackTrace();
          }
       }

       public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
          doGet(req, res);
       }
       
       public void receiveResponse(String restypestr, String resstr) throws RemoteException {
          try {
             System.out.println("Generating request");

             out.println("<html>");
          
             out.println("<head>");
             out.println("<title>" + "Request Servlet" + "</title>");
             out.println("</head>");

             out.println("<body>");
             out.println("Receiving Response");
             out.println(resstr);
             out.println("</body>");
             
             out.println("</html>");
             
             out.close();
          }
          catch (Exception ex) {
             System.out.println("Exception: receiveResponse");
             ex.printStackTrace();
          }
       }
    }

    Thanks

    Tim Pierson

    Threaded Messages (3)

  2. Servlet and RMI Callback[ Go to top ]

    Tim,
    Servlets Run in a multi threaded env. And you are caching in the request and response objects(as an instance variable). Imagine your servlet being called by multiple users(multiple browser), then your request and response object will be overwritten for every request. So even if you were able to successfully callback a method, you will be sending response to different client! Correct me if I am wrong here.

    I know I am not solving your problem. But I do see an inherent flaw in this model. Keeping your RMI requirement aside, I would use a Command Pattern and create a command object for each request and execute the command(which in effect sends a response back to the client).

    public interface ICommand
    {
      execute(ServletRequest req, ServletResponse resp);
    }

    public class Command implements ICommand
    {
       execute(ServletRequest req, ServletResponse resp)
       {
          out = resp.getWriter();
          // send your response
       }
    }

    public class xxxxRequestServlet extends xxxxServlet implements xxxxResponse {

       public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
     ...
     new Command().execute( req, resp );
     ...
    }

    I don't know if this helps.

    --Ganesh

  3. Servlet and RMI Callback[ Go to top ]

    Ganesh

    Thanks for your reply. I agree with you about what you say but, at the moment, I'm trying to do a 'proof of concept', experimenting, I guess. I set the servlet as a 'SingleThreadModel' in a parent class.

    I did manage to get everything working with one major caveat. I didn't mention before that the RMI server is in fact a Bean wrapped as an ActiveX control using the ActiveX Bridge in the Plug-In. When using this scenario I get the correct response from the server (Bean) but when trying to use the 'out.println' methods of the PrintWriter I get nothing (no errors either), although I know that I am getting the correct response as I can redirect it to 'System.out'.

    When I use a Java server simulating the ActiveX Bean, everything works, the correct HTML is shown in the browser. The way I have it setup is that the ActiveX bean fires an event into a Visual Basic application containing a request. The VB app then talks to a document management system and then calls a method in the ActiveX Bean to send the response back to the servlet that kicked everything off.

    Maybe not the best solution to my problem, but I am checking it out.

    Tim
  4. Servlet and RMI Callback[ Go to top ]

    I agree with Ganesh, there is a flaw in your thinking. When the RMI object calls the servlet back, the web browser has already received its response from the doGet, and the user is likely off to another page.

    So when you do out.println, there is no client to receive it.

    here are to ideas that would work:

    [idea1]

    doGet( ... )
    {
        remoteObject = getRemoteObject()
        String result = removeObject.performOperation()
        out.println( result)
    }

    [idea2]

    String _result;
    boolean _receivedResult = false;

    callback( String result )
    {
       _result = result;
       _receivedResult = true;
    }

    doGet( ... )
    {
       remoteObject = getRemoteObject();
       remoteObject.setCallback( this );
       remoteObject.performOperation();

       while ( _receivedResult == false )
       {
          // sit on our ass
       }

       out.println( _result )
    }

    ---------------------------

    the second idea is not very nice, and i haven't really thought the implementation through. but basically it seems you're trying to call an asychronous operation on a remote object, you're going to have to wait for it to finish. so you may as well call a sychronous operation.

    - Alex