Below are the lines taken from Head First Servlets and JSP
1 The filter passes the request and response to the servlet, and waits patiently for its chance to compress stuff.
2a The servlet does its thing,creating output, blissfully unaware that this very same output was supposed to be compressed.
2b The output goes back through the Container and...
2c It’s sent back to the client!Hmmm... this could be a problem.The filter was hoping to have a chance to do something to the output (compress it) before the output went to the client.
3 The call to chain.doFilter() has returned, and the filter was hoping to grab the output and and start compressing...
EXCEPT it’s too late! The output was already sent to the client! The Container doesn’t buffer the output for the filter.
By the time the filter’s own doFilter() method is at the top of the (conceptual) stack, it’s too late for the filter to affect the output.
What I didn't understand is the point no. 3 ,where it is said that "The output was already sent to the client".
Let's say we have two filters (FA and FB) and a servlet (SA).Whenever the client requests SA, the container will redirect the request first to FA and then to FB which in turn redirect it to SA (Please correct me in case).And when SA send the response to client it will first pass to FB and then FA and then to client(skeptical).
But according to the book, the response will be sent directly to client by SA but the control will be move from SA to FB and then FA.
By Defination : A filter dynamically intercepts requests and responses to transform or use the information contained in the requests or responses.
Filters typically do not themselves create responses, but instead provide universal functions that can be "attached" to any type of servlet or JSP page.
Also filters can be used to transform the response from a servlet or a JSP page.
In your example, if we have two filters (FA and FB) and a servlet (SA).Whenever the client requests SA, the container will redirect the request first to FA and then to FB which in turn redirect it to SA and then SA send the response directly to client without any filter invocation.
Enthusiasm is the engine of success!!
SCJP 1.4, OCPJP6
But if SA send response directly to the client , then what about the call stack which was created on invocation of chain.doFilter() of FA and FB and invocation of doGet()/doPost() of servlet SA.
then what about the call stack which was created on invocation of chain.doFilter() of FA and FB and invocation of doGet()/doPost() of servlet SA.
The thing here to understand is that you will return to the filter, but you can't do anything anymore with the response unless you have used something to redirect the outputstream (a response wrapper).
A filter that modifies a response must usually capture the response before it is returned to the client. The way to do this is to pass a stand-in stream to the servlet that generates the response. The stand-in stream prevents the servlet from closing the original response stream when it completes and allows the filter to modify the servlet's response.
normally a response gets committed when the Servlet call (e.g. doGet() or doPost()) ends, or when flush() is called on the response or when the response buffer is full.
Bottom line here is that all of them occur before the filter is called for the second time. To prevent that you will have to use a wrapper ( that will override certain methods of the HttpServletResponse object, especially those that will normally close the stream)