Filter and request dispatching

In this post, you will learn:

  • What is the role of <dispatcher> element in filter-mapping?
  • How to invoke filters even in case of internal forwarding and inclusion?

Filter and request dispatching:

In addition to a direct request, a servlet can be invoked internally through forwarding or inclusion. If a filter is associated to a servlet then will it inovke when a request is internally forwarded to the servlet or its response is included to another servlet’s response?

By default, a filter which is associated to a servlet, is invoked only when a direct request is received for the servet i.e. in case of internal forwarding & inclusion, the filter is not invoked. If a filter is to be invoked even in case of forwarding and inclusion then additional configuration is to be provided with the help of <dispatcher> sub element of <filter-mapping> in web.xml.

Commonly used values of the <dispatcher> sub element of <filter-mapping> are:

1. REQUEST: It is the default value. It represents that the filter is to be invoked when a direct request is received for the URL specified in <url-pattern> sub element of <filter-mapping>.

2. FORWARD: It represents that the filter is to be invoked when a request is forwarded to the specified URL.

3. INCLUDE: It represents that the filter is to be invoked when the response of the specified URL component are included to the response of current request.

Note: Setting the non-default values such as FORWARD or INCLUDE of <dispatcher> element overrides the default behaviour i.e. filter will not be invoked in case of direct request. If it is to be invoked in direct request as well as inclusion & forwarding then all the values including the default need to be set.

Practical example of filter and request dispatching:

First, the index.html :

Direct Request to the processingServlet <br/>
InDirect Request to the processingServlet

Second the HeaderFooterFilter. It adds header and footer to the response generated by the processingServlet.

package com.techmentro.learningpad;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;


public class HeaderFooterFilter implements Filter {

	//FilterConfig refrenceVariable to store the reference of the FilterConfig object of the filter
	private FilterConfig config;
	
	@Override
	public void init(FilterConfig config) throws ServletException {
		// Reference of the FilterConfig object provided by the server is saved for future use.
		this.config=config;
	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		//To generate the header & footer output stream is obtained.
		PrintWriter out=response.getWriter();
		//Header is generated
		out.println("<b>This header is generated by the filter.</b><hr/>");
		//next component is get invoked
		chain.doFilter(request, response);
		//Footer is generated
		out.println("<hr/><b>This footer is generated by the filter.</b>");
		//output stream is closed.
			}

	
	@Override
	public void destroy() {	}

}

Third, the ForwardingServlet. It forwards requests to the ProcessingServlet.

package com.techmentro.learningpad;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;


public class ForwardingServlet extends HttpServlet 
{
	public void doGet(HttpServletRequest request, 
			HttpServletResponse response)
			throws ServletException, IOException {
		//Obtaining RequestDispatcher for processingServlet
		RequestDispatcher rd=request.getRequestDispatcher("/processingServlet");
		//forwarding request to the processingServlet.
		rd.forward(request, response);
	}
}

Fourth, the ProcessingServlet. It generates a single line response.

package com.techmentro.learningpad;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;


public class ProcessingServlet extends HttpServlet 
{
	public void doGet(HttpServletRequest request, 
			HttpServletResponse response)
			throws ServletException, IOException {
	
		response.setContentType("text/html");
		PrintWriter out=response.getWriter();
		out.println("This response is generated by a servlet.<br/>");
		//output stream isn't closed in the servlet because it is used by the filter in post processing.
	}
}

Fifth, the web.xml. It contains the configuration of the filter and the servlets.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 
 
 <!--Filter configuration  -->
 <filter>
 <filter-name>f1</filter-name>
 <filter-class>com.techmentro.learningpad.HeaderFooterFilter</filter-class>
  </filter>
 
 <filter-mapping>
 <filter-name>f1</filter-name>
 <url-pattern>/processingServlet</url-pattern>
 <dispatcher>REQUEST</dispatcher>
 <dispatcher>FORWARD</dispatcher>
 </filter-mapping>
 
 <!--Servlets configuration  -->
 <servlet>
 <servlet-name>s1</servlet-name>
 <servlet-class>com.techmentro.learningpad.ForwardingServlet</servlet-class>
 </servlet>
 <servlet-mapping>
 <servlet-name>s1</servlet-name>
 <url-pattern>/forwardingServlet</url-pattern>
 </servlet-mapping>
 <servlet>
 <servlet-name>s2</servlet-name>
 <servlet-class>com.techmentro.learningpad.ProcessingServlet</servlet-class>
 </servlet>
 <servlet-mapping>
 <servlet-name>s2</servlet-name>
 <url-pattern>/processingServlet</url-pattern>
 </servlet-mapping>
 
</web-app>

To test this application use the following steps:

1. Deploy the application and using the hyper links of index.html, send direct and indirect requests to the processingServlet. In both the case the response will contain header & footer generated by the filter i.e. filter will invoke in direct request as well as forwarding.

2. Now comment the <dispatcher>FORWARD</dispatcher> element in web.xml and again send direct and indirect requests to the processingServlet. This time header & footer will be generated only in direct request.

3. Uncomment the <dispatcher>FORWARD</dispatcher> element and comment the <dispatcher>REQUEST</dispatcher> element in web.xml and again send direct and indirect requests to the processingServlet. This time header & footer will be generated only in case of indirect request.


Its time to recap the main concepts:

  1. By default, a filter isn’t invoked in case of internal forwarding and inclusion.
  2. <dispatcher> sub element of <filter-mapping> element of web.xml is used to invoke filter in case of forwarding and inclusion.
  3. If FORWARD & INCLUDE values of dispatcher element are set for a filter then REQUEST need to be also set if the filter is to be invoked in case of direct requests.
If you like the post, then share it...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *