doFilter called twice, intended behaviour?


doFilter called twice, intended behaviour?



I'm working through the Java EE servlet tutorial and tried the mood example. I noticed the doFilter is getting called twice, once the servlet call is in the chain and the second time it isnt.



I added some printlns in the TimeOfDayFilter.java and in the MoodServlet.java to show this.



TimeOfDayFilter.java:


...
System.out.println("TimeOfDay before"); //added
chain.doFilter(req, res);
System.out.println("TimeOfDay after"); //added
...



MoodServlet.java:


...
response.setContentType("text/html;charset=UTF-8");

System.out.println("MoodServlet"); //added

PrintWriter out = response.getWriter();
...



The result from the glassfish server (3.1) window when calling the servlet is the following:


INFO: mood was successfully deployed in 406 milliseconds.
INFO: TimeOfDay before
INFO: MoodServlet
INFO: TimeOfDay after
INFO: TimeOfDay before
INFO: TimeOfDay after



Is this intended behaviour? If so, what is the reason for the extra call?





Just do System.out.println(request.getRequestURI()) to learn which request exactly hit the filter. And, press F12 in webbrowser to track all fired HTTP requests.
– BalusC
Jan 16 '16 at 11:59


System.out.println(request.getRequestURI())




4 Answers
4


chain.doFilter(request,response);



This will pass the control to the servlet the filter is associated with.
But after the corresponding servlet is executed, the control comes back at the end of the above line and all the lines thereafter in the current doFilter() is executed.



If you want to pass the control permanently to the servlet and not letting it return to the filter, just add a


return;



at the end of chain.doFilter(request,response) line in the current filter.





This answer doesn't explain the symptoms described in the question in any way.
– BalusC
Jan 16 '16 at 12:00



Yes it is, Filter is executed twice in the life cycle, first calls when request from client come to servlet and second time when response is served to the client after execution of servlet.



The order of execution is somehow looks like this.



Filter lifecycle





Thanks for the answer, but a few more questions: - One could also interpret the reponse arrows as being the code that happens after the chain.doFilter call (as in the line of my code snippet which prints "TimeOfDay after"), but it is really a fresh call of the filters DoFilter method? - Is there a way to determine if it is the first or the second time that its called (request or response part)? - Is there a way not to have the call on the way back?
– user1348661
May 20 '13 at 10:51






Following topic on servlet documentation explains the whole concept in detail, Understanding and Using Servlet Filters You can use some request parameter or use following if statement for that if(res instanceof HttpServletResponse) to defreetiate
– Zeeshan Bilal
May 20 '13 at 12:15



if


if(res instanceof HttpServletResponse)





Ok, I get the picture (but the if statement doesnt work with me, always returns true, I'll dive into it). Thx
– user1348661
May 20 '13 at 18:07





@Zeeshan Bilal: I think your answer is wrong. For each request, the method doFilter is called once. The statements in doFilter are executed until "chain.doFilter(req, resp)" is reached. "chain.doFilter(req, resp)" causes the execution to be continued in the next filter in chain or in the servlet. After the sequence of filters and the servlet is executed, the doFilter-Method is continued after "chain.doFilter(req, resp)".
– JimHawkins
Jun 3 '15 at 9:20






This answer is pure nonsense. Please fix or delete it. All those upvotes generated by ignorant nitwits are misleading to future readers.
– BalusC
Jan 16 '16 at 11:58




The reason why the filter is called twice are the images used in the response creation, as for instance


out.println("<img src="resources/images/duke.snooze.gif" alt="Duke sleeping"/><br/>");



Please see the log output


2016-01-16T11:25:34.894+0100|Info: TimeOfDay doFilter method before sending to chain

2016-01-16T11:25:34.895+0100|Info: MoodServlet get method called

2016-01-16T11:25:34.895+0100|Info: TimeOfDay doFilter method after sending to chain

2016-01-16T11:25:34.942+0100|Info: TimeOfDay doFilter method before sending to chain

2016-01-16T11:25:34.942+0100|Info: TimeOfDay doFilter method after sending to chain



src in img tag is nothing else than the second request for server to take care of. Please notice the url pattern used in the @WebFilter


@WebFilter(filterName = "TimeOfDayFilter",
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "mood", value = "awake")})



It will intercept all the requests coming into mood application. As an exercise simply try to remove images from the response or change url pattern to intercept only requests ending up in MoodServlet


@WebFilter(filterName = "TimeOfDayFilter",
urlPatterns = {"/report"},
initParams = {
@WebInitParam(name = "mood", value = "awake")})



Both will result in one call of doFilter as you originally expected


2016-01-16T11:28:53.485+0100|Info: TimeOfDay doFilter method before sending to chain

2016-01-16T11:28:53.486+0100|Info: MoodServlet get method called

2016-01-16T11:28:53.487+0100|Info: TimeOfDay doFilter method after sending to chain





1) HTML in Servlet is bad practice. HTML belongs in JSP. JSP is a tool much more suitable for defining HTML code which should be emitted. You do not need to fuzz with double quotes at all. 2) It are not necessarily only images. Any asset/resource whose URL matches the filter's URL pattern could be a candidate (CSS, JS, favicons, etc).
– BalusC
Jan 16 '16 at 12:02






Hi BalusC, thanks for additional in deep and handy ideas, as usually. The whole example is from the official Java EE 7 tutorial I went through today and it made me ask the very same question which I found here :) It is only a basic showcase of servlet, filter and listener tutorial creators have used. Creation of html response in servlet is there only for simplicity of course.
– SilverFox
Jan 16 '16 at 13:35





(Yes, technically also jsp turns into servlet, but you understand my point :) )
– SilverFox
Jan 16 '16 at 13:43





Nope. I'm outputting (HttpServletRequest)servletRequest).getRequestURL() and that's not the case. The filter is called twice.
– isapir
Sep 5 '16 at 20:47


(HttpServletRequest)servletRequest).getRequestURL()



The Filter.doFilter method is called once per request. You can execute some code before other filters in the chain are called and also afterwards (in the order specified in the filter chain, as per the web.xml filter-mapping order),
something like the following example:


Filter.doFilter


web.xml filter-mapping


public MyFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
codeToExecuteBeforeOtherFiltersInTheChain(request, response);

chain.doFilter(request, response);

codeToExecuteAfterOtherFiltersInTheChain(request, response);

}
}



If your filter is configured to dispatch REQUEST and FORWARD requests, then the MyFilter.doFilter method will be called once for the original request and once if the request has been forwarded:


REQUEST


FORWARD


MyFilter.doFilter



Configure filter mapping using web.xml file:


web.xml


...
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
...



Configure filter mapping using @WebFilter annotation:


@WebFilter(urlPatterns = "/*", dispatcherTypes = {
DispatcherType.REQUEST, DispatcherType.FORWARD
}) public MyFilter implements Filter {
....
}



To be able to check if the request has been forwarded, you can use the request attribute described here: How to know when the request is forwarded in a RequestWrapper object



For details about filters see: https://docs.oracle.com/cd/B32110_01/web.1013/b28959/filters.htm






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Opening a url is failing in Swift

Export result set on Dbeaver to CSV