Servlet Filters – Beginner’s Guide

October 28 20092 Commented

Categorized Under: Java

This tutorial is based on the following software environment.

Windows Vista Home Premium, Eclipse 3.5, JDK 1.6, Tomcat 6

Filters may be used for large number of tasks like compressing response, modifying request and response headers, logging, change the content type, authenticating the user etc. For eg, suppose you want to check whether the user is already logged in or not. If you are using JSP, you have to write the authentication check in another JSP and include it in all JSP pages. Rather than including it in all pages, you may create an authentication filter class and attach it to all JSP pages. Mapping Filter with resources is done in web.xml configuration file so that your JSP or Servlet will remain much clean containing code for specific purposes.

There are three interfaces defined in javax.servlet package.

  • FilterConfig – This object acts as configuration object for filter which pass information to filter during initialization. For eg, you may set initialization parameters in web.xml file for filter which could be accessed from this object. It also allow us to get a reference to ServletContext object. Every servlet container has its own implementation of FilterConfig interface.
  • FilterChain – This object is again created by servlet container which provides a convenient method to invoke next filter in the chain or final resource. The method is doFilter (ServletRequest request, ServletResponse response). Suppose one servlet is attached with two filters. In first filter calling doFilter() method of FilterChain object invokes second filter and calling the method in second filter invokes servlet itself.
  •  Filter – This is the filter object which actually performs filtering tasks. For creating Filter you have to declare a class which implements this interface. Like servlet, this also provides life cycle methods such as init() and destroy(). You have to implement doFilter(ServletRequest request, ServletResponse response, FilterChain chain) method which actually does filtering task. This method is called by servlet container for every request/response.

 In doFilter() method, the following steps are executed.

  • When a client makes HTTP request to a resource, the servlet container checks whether it is associated with filter.
  • If yes, the filter’s doFilter method is called.
  • Inside doFilter() method we may intercept request object and may modify the same. After that we call doFilter() method of FilterChain object. Here it invokes next filter in chain. If no more filters are available, final resource (Servlet, JSP etc) is called.
  • The resource like Servlet or JSP process the request and send response back to client. This again is passed through doFilter method of filter object. All statements written after doFilter() method of chain object is executed again.
  • Finally the response is sent back to client

The skeleton of doFilter() method is given below.

public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException{
      //preprocess statements for request/response objects
      ..................................................................
      ..................................................................     
      //call doFilter() of chain object, invoke next filter or resource     
      chain.doFilter (request, response);     
      //post-processing of request/response objects     
      ..................................................................
      ..................................................................
}

OK, now let us create a Filter example. If you haven’t had Eclipse IDE with Tomcat , refer the following tutorial.

Installing and Configuring Eclipse with Tomcat in Windows

If you are not comfortable with Servlets, refer the following tutorial.

Introduction to Servlets

Open Eclipse. Java EE perspective is the default perspective. If you are not sure go to Window–>Open Perspective–>Other. Select Java EE and click OK.

Go to File–>New–>Dynamic Web project. Project Wizard appears.

servletexample_1

Give the project name as FilterExample. All other options do not require modification if you are using Eclipse with Tomcat as server. If you have configured multiple servers you may change the target runtime. Click Finish button. Now we have to add the project under server. Go to server window, right click on server entry and select Add and Remove. Move the project from left to right window in properties box. Click Finish button.

OK, now the project is added under server. Let us create a servlet. All servlet classes should be defined in Java Resources (src) folder. In project explorer expand the project. Right click on src folder and select New–>Servlet.

Create Servlet wizard appears. Specify the package name as example and Class name as GreetingsServlet. Press Next button.

filters_1

Next screen is about URL Mappings for servlet related to deployment descriptor. Keep it as default and press Next button. Uncheck the option Constructors from superclass. Uncheck the option doPost method. We just require doGet method stub which we want to override in our example. Press Finish button.

GreetingsServlet.java file opens in editor. Now paste the following code in doGet method skeleton.

response.setContentType("text/html");
PrintWriter out = response.getWriter();
String name = (String)request.getAttribute("name");
out.println("Hello "+name+", how are you?");

We have to write one import statement for PrintWriter class. Add the following statement just below other import statements in top of the file. Save the file.

import java.io.PrintWriter;

Save the file. Ok, now let us create a filter. In project explorer write click on src folder and select New–>Filter

 filters_2

Create Filter wizard appears. Give the package name as example and class name as FirstFilter. Press Next button.

 filters_3

Next screen is about filter mapping. You may either give URL pattern or servlet name to attach the filter. If you want to apply filter to more than one resource it is better to give URL pattern. Select default mapping /FirstFilter and press edit button. In the pattern box give the entry as /GreetingsServlet. If we want to apply the filter for resource which is coming from RequestDispatcher object using methods like forward, include etc, you may select appropriate dispatchers. In our example this  is not required. Press Next button.

filters_4

 

Next screen is about adding more interfaces which is not required in our case. Press finish button. FirstFilter.java appears in editor. Now place the following code snippet inside doFilter() method just above chain.doFilter() statement.

if (request.getAttribute("name")==null){
      request.setAttribute("name", "Jinoy");
}

 filters_5

Save the file. Now let us test our servlet. 

Go to server window and start the server. Once server is started go to browser, paste the following URL and hit enter.

http://localhost:8080/FilterExample/GreetingsServlet

If you could see the greetings message in browser, you have finished the first step towards filter. Now let us walk through the code. In filter class, doFilter() method we check whether attribute name is bound to request object. If not, we set the attribute name with value. In GreetingsServlet, we send a greetings message to the user by taking the attribute value of name. When user send HTTP request, it is first passed through the filter and doFilter() method is executed. All statements which are written above chain.doFilter() method are executed. Then the servlet is invoked. We haven’t written any post-processing statements in doFilter() method. So the response object is not modified and sent back to client.

Please note that attribute is different than parameters. Parameters are name/value pairs which are either submitted from HTML form or accessed from web.xml file initialization parameters. Parameters could not be changed in request object but we could add/modify attributes. Since attributes are objects, we have to cast them to our original class. In our example we cast name attribute value to string.

 As in the case of servlets, filters also require configuration information in web.xml file. Since you are using Eclipse, this is automatically created for you. However, let us walk through the xml elements in detail.

In Eclipse project explorer open web.xml file from WebContent/WEB-INF folder.

filters_6

Like servlets, we need two elements, <filter> and <filter-mapping>.

<filter> element consists of the following child elements.

  • <display-name> – short name or alias which is optional
  •  <filter-name> – name of the filter refered by web.xml file, which is a required element.
  • <description> – description about the filter. Optional
  • <filter-class> – full qualified filter class. Required
  • <init-param> – initialization parameters for filter which could be accessed from FilterConfig object.

<filter-mapping> consists of the following child elements.

  • <filter-name> – name of the filter defined by <filter-name> child element under <filter> element. Required
  • <url-pattern> – URL pattern to which the filter should be applied. Pattern is resolved to context path. This is required if we do not specify <servlet-name> element.
  • <servlet-name> - name of the servlet to which filter should be applied. This is required if we haven’t specified url-pattern element.
  • <dispatcher> – method type for which the filter should be applied. For eg, if the servlet is called using forward method of  RequestDispatcher object, you should use <dispatcher>FORWARD</dispatcher> element.

 The web.xml elements for our filter is given below.

<filter>
     <display-name>FirstFilter</display-name>
     <filter-name>FirstFilter</filter-name>
     <filter-class>example.FirstFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/GreetingsServlet</url-pattern>
</filter-mapping>

Ok, now let us get into a more complex example. In the previous example we haven’t modified response object. Post-processing response objects is not so easy because if we close the servlet outputstream, we could not be able to modify it in filter. One alternative way is to pass the wrapper of response object so that we may modify the response stream later. Java provides a convenient response wrapper class called HttpServletResponseWrapper. This class merely delegates to underlying response object in its default methods. We may override these methods and give our own implementation. Why should we use wrapper class? HttpServletResponse is an interface and different servlet containers have their own implementation. So we just can’t override any class and extend the features.

In the previous example we have given greetings message. Now we want to add additional feature to send back the greetings message in uppercase format.

In project explorer, right click on src folder and select New–>Class. Give the package as example and Class name as FilterServletOutputStream. Press finish button.

Replace the entire code with the following snippet.

package example;
 
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
 
import javax.servlet.ServletOutputStream;
 
public class FilterServletOutputStream extends ServletOutputStream {
 
	DataOutputStream output;
	public FilterServletOutputStream(OutputStream output) {
		// TODO Auto-generated constructor stub
		this.output = new DataOutputStream(output);
	}
 
	@Override
	public void write(int arg0) throws IOException {
		// TODO Auto-generated method stub
		output.write(arg0);
	}
 
	@Override
	public void write(byte[] arg0, int arg1, int arg2) throws IOException {
		// TODO Auto-generated method stub
		output.write(arg0, arg1, arg2);
	}
 
	@Override
	public void write(byte[] arg0) throws IOException {
		// TODO Auto-generated method stub
		output.write(arg0);
	}
 
}

Save the file. Again create another class in the same package with class name as GreetingsResponseWrapper. Replace entire code with the following snippet.

package example;
 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
 
public class GreetingsResponseWrapper extends HttpServletResponseWrapper {
 
	ByteArrayOutputStream output;
	FilterServletOutputStream filterOutput;
	PrintWriter pw;
 
	public GreetingsResponseWrapper(HttpServletResponse response) {
		super(response);
		// TODO Auto-generated constructor stub
		output = new ByteArrayOutputStream();
	}
	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		// TODO Auto-generated method stub
		if (filterOutput==null){
			filterOutput = new FilterServletOutputStream(output);
		}
		return filterOutput;
	}
 
	@Override
	public PrintWriter getWriter() throws IOException {
		// TODO Auto-generated method stub
		if (filterOutput==null){
			filterOutput = new FilterServletOutputStream(output);
		}
		if(pw==null){
			pw = new PrintWriter(filterOutput, true);
		}
		return pw;
	}
	//get the output from byte stream
	public byte[] getDataStream(){
		return output.toByteArray();
	}
 
}

Save the file. Now we have to modify the doFilter method of FirstFilter class. Replace the method content with the following code.

if (request.getAttribute("name")==null){
	request.setAttribute("name", "Jinoy");
}
// pass the response wrapper along with request
GreetingsResponseWrapper responseWrapper = new GreetingsResponseWrapper(
                    (HttpServletResponse)response);
chain.doFilter(request, responseWrapper);
//now get data from wrapper
String result = new String(responseWrapper.getDataStream());
//convert it into upper case
result = result.toUpperCase();
//print the output to original response stream
response.getWriter().println(result);
response.getWriter().close();

Save the file. Restart tomcat server. Go to browser, paste the following URL and hit enter.

http://localhost:8080/FilterExample/GreetingsServlet

The message is appeared in upper case! Ok, now let us walk through the code.

FilterServletOutputStream extends ServletOutputStream class. We declared one DataOutputStream instance variable. DataOutputStream is a filter stream class which allow us to write byte stream in machine independant manner. Since write() method is abstract in nature, we have overriden it. Rather than writing to standard servlet output stream we are writing into DataOutputStream instance variable. The DataOutputStream is created from OutputStream object which is passed as constructor parameter.

GreetingsResponseWrapper extends from standard HttpServletResponseWrapper. Here we declare one ByteArrayOutputStream instance variable which is used to pass into FilterServletOutputStream object. We override two methods, getOutputStream() and getWriter() and return FilterServletOutputStream object.

In our filter class we create GreetingsResponseWrapper object and is passed into doFilter method of chain object rather than passing original response object.

When we call println() method of PrintWriter object in GreetingsServlet, the output is not written into standard servlet output stream. It is written into the  byte array stream of wrapper response object.

Finally in filter class post-processing section, we get the data from ByteArrayOutputStream object, convert into upper case and print to standard output stream.

Ok, I hope you got fair enough idea about filters. Now go and have one drink.

cheers,

2 Responses to “Servlet Filters – Beginner’s Guide”

  1. iqbal says:

    The screenshots are useful to easy relate with real time systems

  2. tea says:

    Filters are important for a number of reasons. First, they provide the ability to encapsulate recurring tasks in reusable units. Organized developers are constantly on the lookout for ways to modularize their code. Modular code is more manageable and documentable, is easier to debug, and if done well, can be reused in another setting.

Leave a Reply

*