Wednesday, February 09, 2011

Go deep into servlet3

Deep into Servlet3

Servlet is the most widely used technology in j2ee platform, many developers know it, but not really understand it. In this article I would
like to share some more detailed understanding of it.

Response and socket connection.
The response object encapsultes all information to be returned from the server to the client. A socket connection is a physical connection
between client and server. In HTTP 1.0, each reqeust/response must establish a new connection, when servelt return the response to the client,
the connection will be closed wa well. But HTTP 1.1 introduces persistent connection, in this case, when servlet return the response to
the client, the connection will not be closed, the client can send a new request on this connection until either side closes the connection
explicitly. Anyway we must know that resposne is'nt a abstract of connection in the servlet context.

- Response.flush(): will force the content in the buffer to be written to the client, the response will be considered as committed.
- Response.reset()/resetBuffer(): the reset() method clears the data in buffer when the response isn't committed. Headers and status code
set by the servlet prior to the reset call must be cleared as well. resetBuffer() will only reset the data in buffer.
- Response.setBufferSize(): The servlet can request a preferred buffer size, but the buffer assigned is not required to be the sieze requested
by the servlet, but must be at least as large as the size requested.

The isCommitted() method return a boolean value indicating whether any response bytes have been returned to client. A servlet container is
allowed, but not required, to buffer output going to the client for efficiency purpose.When using a buffer, the container must immediately
flush the contents of a filled buffer to the client. If this is the first data that is sent to client, the response is considered as committed.

To be successfully transmitted back to the client, headers must be set before the response is committed. Headers set after the response is
committed will be ignored by the servlet container.
Below methods will make the response to be committed:
- Response.flushBuffer()
- Response.getWriter().flush();
- Response.sendError(): The sendErro() method will set the appropriate headers and content body for an erro message to return to the client.
- Response.sendRedirect(): The sendRedirect() method will set the appropriate headers and content body to redirect the client to a different URL.
NOTE: sendErro() and sendRedirect() will have the side effect of committing the response, if it has not already committed,and terminating it.
No further outpu to the client should be made by the servlet after these methods are called. If data is written to the response after these
methods are called, the data will be ignored.

When a response is closed,the container must immediately flush all remaining content in the response buffer to the client. the following events
indicate that the servlet has satisfied the request and that the response object i to be closed:
- The termination of the service() method os the servlet.
- The amount of content specified in the setContentLength() method of the response has been greater than zero and has been written to the response.
- The sendError() method is called.
- The sendRedirect() method is called.
- The complete() method on AsyncContext is called.

Each response object is valid only within the scope of a servlet's service() method, or within the scope of a filter's doFilter() method, unless
the associated request object has asynchronous processing enabled for the component. If asynchronous processing on the associated reqeust is started,
then the reqeust object remains valid until complete() method on AsyncContext is called. Containers commonly recycle response objects in order to
avoid the performance overhead of response object creation.

Dispatcher forward/include.
The Container Provider should ensure that the dispatch of the request to a target servlet occurs in the same thread of the same JVM as the original
- RequestDispatcher.include(): It can ben called at any time. The target servlet of the include method has access to all aspects of the request
object, but its use of the response object is more limited.
It can only write information to the ServletOuputStream or Writer of the response object and commit a response by writing content past the end of
the response buffer, or by ecplicitly calling the flushBuffer() method of the ServletResponse interface. It cannot set headers or call any method
that affects the ehaders of the response.
When return from target servlet, you can return content in the buffer to the client if the response object isn't closed, or even set headers if the
response object isnot committed.
- RequestDispatcher.forward(): This method may be called by the calling servlet only when no output has been committed to the client. If outpu data
exists in the response buffer that has not been committed, the content must be cleared before the target servlet's service() method is called. If
the response has been committed, all IllegalStateException must be thrown.
When return from the target servlet, the response object is closed, you cannot apply any modification to it any more.

Asynchronous processing.
Refer to
But when check the sourcecode of class SlowWebService which is a ServletContextListener, I found that there is a infinite loop in the contextInitiate()
method, that means when container try to lunch a web application, it will never be successful. I really don't understand why put a infinite loop block
there, my tests in jetty and tomcat both demonstrate that container will fall into the infinite loop and cannot go forward to finish the launch and cannot
be ready to serve any request from the client.

No comments: