5.4 Response Buffering

Java Servlet Programming, 2nd Edition > 5. Sending HTML Information > 5.4 Response Buffering

 
< BACKCONTINUE >

5.4 Response Buffering

Beginning with Servlet API 2.2, a servlet has control over whether the server buffers its response and may dictate how large a buffer the server can use. In previous versions of the API, most web servers implemented response buffering as a way to improve performance; exactly how large that buffer was depended on the server. Generally, servers had buffers in the neighborhood of 8K.

A response buffer allows a servlet to write some amount of output with a guarantee that the response won't be immediately committed. If the servlet finds an error, the status code and headers can still be changed so long as the buffer has not been flushed.

Response buffering also provides a simple way to avoid the potentially difficult content length precalculation. A servlet can use buffering to automatically calculate the content length, as shown in Example 5-2.

Example 5-2. A Servlet Using Buffering to Support Persistent Connections
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class KeepAlive extends HttpServlet {   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     res.setContentType("text/html");     // Ask for a 16K byte response buffer; do not set the content length     res.setBufferSize(16 * 1024);     PrintWriter out = res.getWriter();     out.println("<HTML>");     out.println("<HEAD><TITLE>Hello World</TITLE></HEAD>");     out.println("<BODY>");     out.println("<BIG>Less than 16K of response body</BIG>");     out.println("</BODY></HTML>");   } }

This servlet calls setBufferSize( ) to request a 16K-byte minimum response buffer, then sends its response body as usual. The server uses an internal buffer at least 16,384 bytes large to hold the response body and waits to send the content to the client until either the buffer fills or the servlet requests a buffer flush. Should the full response body fits within the buffer, the server can (but is not required to) automatically set the response Content-Length header.

It is important to note that buffering responses comes with a price. Buffering all the output and sending it all in one batch requires extra memory, and it may delay the time at which a client begins receiving data. For servlets with short responses, persistent connections make sense, but for servlets with long responses, the memory overhead and delay probably outweigh the benefit of opening fewer connections.

It is also important to note that not all servers and not all clients support persistent connections. That said, it's still appropriate for a servlet to set its content length or buffer its output so the server can determine the length. The content length information will be used by those servers and clients that support persistent connections and ignored by the others.

5.4.1 Controlling the Response Buffer

Five methods in ServletResponse provide control over response buffering. You can use setBufferSize( ) to tell the server the minimum buffer size (in bytes) that your servlet will accept:

public void ServletResponse.setBufferSize(int size)   throws IllegalStateException

The server may provide a larger buffer than requested it may want to keep buffers in 8K blocks, for example, to facilitate reuse. A larger buffer allows more content to be written before anything is actually sent, thus providing the servlet with more time to set appropriate status codes and headers. A smaller buffer decreases server memory load and allows the client to start receiving data more quickly. This method must be called before any response body content is written; if content has been written, this method throws an IllegalStateException. Use getBufferSize( ) to determine the size of the buffer:

public int ServletResponse.getBufferSize()

This method returns an int indicating how large the current buffer actually is or in the unlikely event no buffering is used.

You can call isCommitted( ) to determine whether any part of the response has actually been sent:

public boolean ServletResponse.isCommitted()

If this method returns true, it's too late to change the status code and headers, and the Content-Length cannot be automatically calculated.

If you need to start over with your response, you can call reset( ) to clear the response buffer and the currently assigned status code and response headers:

public void ServletResponse.reset() throws IllegalStateException

This method must be called before the response has been committed, otherwise it throws an IllegalStateException. The sendError( ) and sendRedirect( ) methods, discussed later, behave similar to this and clear the response buffer, however those methods don't touch the response headers.

You can also force any content in the buffer to be written to the client by calling flushBuffer( ) , allowing the client to begin receiving the content immediately:

public void ServletResponse.flushBuffer() throws IOException

Calling this method automatically commits the response, meaning the status code and headers will be written and a reset( ) will no longer be possible.

Example 5-3 shows a servlet using the reset( ) method to write and then clear content. It prints the default buffer size but to the log instead of the client so that it won't be reset( ) away.

Example 5-3. Managing the Response Buffer
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class Buffering extends HttpServlet {   public void doGet(HttpServletRequest req, HttpServletResponse res)                                throws ServletException, IOException {     res.setBufferSize(8 * 1024); // 8K buffer     res.setContentType("text/html");     PrintWriter out = res.getWriter();     int size = res.getBufferSize(); // returns 8096 or greater     // Record the default size, in the log     log("The default buffer size is " + size);     out.println("The client won't see this");     res.reset();     out.println("Nor will the client see this!");     res.reset();     out.println("And this won't be seen if sendError() is called");     if (req.getParameter("important_parameter") == null) {       res.sendError(res.SC_BAD_REQUEST, "important_parameter needed");     }   } } 


Last updated on 3/20/2003
Java Servlet Programming, 2nd Edition, © 2001 O'Reilly

< BACKCONTINUE >


Java servlet programming
Java Servlet Programming (Java Series)
ISBN: 0596000405
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net