Need help with HttpServletResponse.flushBuffer( )

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Eric West

    Need help with HttpServletResponse.flushBuffer( )

    Greetings-

    I have a web application that has a form that triggers a server process that
    I would like to provide a "Searching. .." page for.

    My strategy was to send the browser the "top half" of a web page, including
    an animated "Searching. .." gif. I write the contents of this page to the
    HttpServletResp onse output, and then flush the buffer (which I had thought
    would cause the bytes written thus-far to make their way to the client). I
    then do the time-intensive operation on the server side (simulated below
    with a 10 second Thread sleep), followed by streaming to the output the
    "bottom half" of the web page, including a META refresh that would cause the
    client to redirect to a "Results" page.

    Unfortunately, what actually happens is that the client (IE 6) waits until
    the entire page is sent, briefly shows the "Searching. .." image, and then
    immediately redirects to the "Results".

    I have tried explicitely setting the bufferSize of the response to be
    smaller than the length of the "top half", but this didn't seem to alter the
    behavior.

    I am serving from Tomcat 5.0.16, which I'm beginning to suspect might be a
    culprit here, somehow micro-managing the buffer until the servlet returns
    from processRequest( ), thus thwarting my flushBuffer( ) strategy.

    Below is the processRequest( ) method of my Servlet. Below that are the two
    halves of the web page. I have removed some domain-specific names and
    modified slightly for readability.

    Thanks in advance for any insight!
    -Eric

    void processRequest( HttpServletRequ est request, HttpServletResp onse
    response) throws ServletExceptio n, IOException
    {
    response.setHea der("Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
    response.setHea der("Cache-Control", "no-cache, must-revalidate");
    response.setHea der("Pragma", "no-cache");

    BufferedInputSt ream inStreamA = null;
    BufferedInputSt ream inStreamB = null;
    BufferedOutputS tream outStream = null;

    try
    {
    response.setCon tentType("text/html");
    outStream = new BufferedOutputS tream(response. getOutputStream ());

    File fileTop = new File(FILE_TOP);
    long halfFileSize= fileTop.length( )/2;
    response.setBuf ferSize(((int)h alfFileSize));

    inStreamA = new BufferedInputSt ream(new FileInputStream (fileTop));

    int byteRead = inStreamA.read( );
    while (byteRead != -1)
    {
    outStream.write (byteRead);
    byteRead = inStreamA.read( );
    }

    outStream.flush ();
    response.flushB uffer();

    try { Thread.sleep(10 000); }
    catch (InterruptedExc eption ignored) { }

    inStreamB = new BufferedInputSt ream(new
    FileInputStream (FILE_BOTTOM));

    byteRead = inStreamB.read( );
    while (byteRead != -1)
    {
    outStream.write (byteRead);
    byteRead = inStreamB.read( );
    }

    outStream.flush ();
    response.flushB uffer();

    }
    catch(Exception e)
    {
    log.log("proble m : " + e);
    }
    finally
    {
    if (inStreamA != null)
    {
    inStreamA.close ();
    }
    if (inStreamB != null)
    {
    inStreamB.close ();
    }

    }

    }


    ==========TOP FILE=========== =

    <html>
    <head>
    <title>Searchin g</title>
    </head>

    <body>

    <img src="images/searching.gif" border="0">

    =============== ===============

    ==========BOTTO M FILE=========


    <META http-equiv=refresh content="0;URL= results.html">

    </body>
    </html>

    =============== ===============


  • Eric West

    #2
    Re: Need help with HttpServletResp onse.flushBuffe r( )

    I should add that I'm using Apache 1.3.29 with mod_jk.

    "Eric West" <ewestNO@SPAMfe deralresearch.c om> wrote in message
    news:trudnaRuK5 [email protected] ...[color=blue]
    > Greetings-
    >
    > I have a web application that has a form that triggers a server process[/color]
    that[color=blue]
    > I would like to provide a "Searching. .." page for.[/color]

    <snipped>


    Comment

    • Silvio Bierman

      #3
      Re: Need help with HttpServletResp onse.flushBuffe r( )


      "Eric West" <ewestNO@SPAMfe deralresearch.c om> wrote in message
      news:h82dnTBBJ6 [email protected] ...[color=blue]
      > I should add that I'm using Apache 1.3.29 with mod_jk.
      >
      > "Eric West" <ewestNO@SPAMfe deralresearch.c om> wrote in message
      > news:trudnaRuK5 [email protected] ...[color=green]
      > > Greetings-
      > >
      > > I have a web application that has a form that triggers a server process[/color]
      > that[color=green]
      > > I would like to provide a "Searching. .." page for.[/color]
      >
      > <snipped>
      >
      >[/color]

      Why do you expect the browser to render a partially received HTML page?

      A more solid approach would be to send a complete "searching. .." page first
      along with an onload action that does an immediate redirect to an URL that
      triggers the actual thing and returns the result.

      Silvio Bierman


      Comment

      • Eric West

        #4
        Re: Need help with HttpServletResp onse.flushBuffe r( )

        [color=blue][color=green][color=darkred]
        > > > I have a web application that has a form that triggers a server[/color][/color][/color]
        process[color=blue][color=green]
        > > that[color=darkred]
        > > > I would like to provide a "Searching. .." page for.[/color]
        > > <snipped>[/color][/color]
        [color=blue]
        > Why do you expect the browser to render a partially received HTML page?[/color]

        First Silvio, thanks for your reply.

        I expect the browser to render a partially received page because a browser
        seems capable of it. That's the behavior I was hoping to trigger with the
        call to HttpServletResp onse.flushBuffe r( ). A browser (obviously) has no
        problem *rendering* snippets of pages. I think what you are suggesting is
        that a browser won't begin to render anything until the server has
        completely finished writing to the Response. In this case, I'd really like
        somebody to explain what flushBuffer( ) is supposed to be for.
        [color=blue]
        > A more solid approach would be to send a complete "searching. .." page[/color]
        first[color=blue]
        > along with an onload action that does an immediate redirect to an URL that
        > triggers the actual thing and returns the result.[/color]

        That is exactly what I am doing, due to the fact that I can't get the
        flushBuffer( ) working. The downside to this approach is that as soon as the
        "Searching. .." page starts the redirect to the server, the gif stops being
        animated, and stays frozen until the result is ready. It's ok, but not at
        all optimal. This seems to be browser-specific behavior. My co-workers
        Firebird browser shows the animation the entire time. Unfortunately, windows
        IE 6 freezes the gif, and this is the browser that I need to support.

        -Eric


        Comment

        • Silvio Bierman

          #5
          Re: Need help with HttpServletResp onse.flushBuffe r( )

          "Eric West" <ewestNO@SPAMfe deralresearch.c om> wrote in message
          news:B_ednTsIZY [email protected] ...[color=blue]
          >
          > First Silvio, thanks for your reply.
          >
          > I expect the browser to render a partially received page because a browser
          > seems capable of it. That's the behavior I was hoping to trigger with the
          > call to HttpServletResp onse.flushBuffe r( ). A browser (obviously) has no
          > problem *rendering* snippets of pages. I think what you are suggesting is
          > that a browser won't begin to render anything until the server has
          > completely finished writing to the Response. In this case, I'd really like
          > somebody to explain what flushBuffer( ) is supposed to be for.
          >[color=green]
          > > A more solid approach would be to send a complete "searching. .." page[/color]
          > first[color=green]
          > > along with an onload action that does an immediate redirect to an URL[/color][/color]
          that[color=blue][color=green]
          > > triggers the actual thing and returns the result.[/color]
          >
          > That is exactly what I am doing, due to the fact that I can't get the
          > flushBuffer( ) working. The downside to this approach is that as soon as[/color]
          the[color=blue]
          > "Searching. .." page starts the redirect to the server, the gif stops being
          > animated, and stays frozen until the result is ready. It's ok, but not at
          > all optimal. This seems to be browser-specific behavior. My co-workers
          > Firebird browser shows the animation the entire time. Unfortunately,[/color]
          windows[color=blue]
          > IE 6 freezes the gif, and this is the browser that I need to support.
          >
          > -Eric
          >
          >[/color]

          Hello Eric,

          Obviously browser could render partial HTML (up to some level) but the fact
          is that there seems to be no agreed upon reason to so you can never be sure
          the browser will do that. There has been some talk in the past about browser
          implementing server-push facilities (look at O'Reilly's servlet book) but
          that never quite make it into the mainstream.
          If you look at the HTTP1.1 protocol you can see why a HTTP server would want
          to flush its buffers, a connection can remain open to accomodate multiple
          HTTP requests.

          Back to your problem: I missed the part about the animated GIF so I can
          understand you dislike the solution (which you already found). You can solve
          this in wo ways:

          You could start the time-consuming server action as soon as the first
          request (that returns the "working... " page) in a separate thread and keep
          returning the working-page while it is not finished (with some delayed
          refresh of X seconds which can be easily done with a HTTP header) and when
          the request comes in after the thread has finished you send the actual
          result. That will keep your animated gif active.

          The other way would be by using a scheme like XMLHTTP. Your working-page
          does not perform a refresh but instead does a JS-level HTTP request that
          gets the actual result. From the JS you could modify the page to show that
          result. For examples look at http://jibbering.com/2002/4/httprequest.html.
          This technique offers very advanced possibilities which go a lot further
          than what you need here. Supported in IE and Mozilla/Netscape. Don't know
          about other browsers though. An alternative for XMLHTTP could always be an
          invisible applet or an invisible IFRAME.

          Hope this helps,

          Silvio Bierman


          Comment

          Working...