Saturday, January 31, 2009

Servlet Filters

This blog intends to answer the following questions :-
  1. What is a Filter?
  2. Why should I use filters in my web application?
  3. How do I use Filters in a web application?
Here is what I have :-
  1. An local installation of tomcat that listens on port number 8080.
  2. A web application called FilterApplicationExample placed in the tomcat-installation-directory/webapps.
  3. The directory structure of every web-application in java should have a format. If you are unaware of the format, please refer to my other posts.
  4. Now I create a java file - MyFilter.java in the WEB-INF/src/examples directory.
  5. This file would house the code that would be executed as a filter for this application.
  6. I also create a Servlet named - 'MyServlet.java' in the WEB-INF/src/examples directory.
  7. This file will house the code for the the servlet that is actually requested by the client.
  8. I also have a file - 'web.xml' in the WEB-INF directory that houses the code that will be used to associate my Filter with the Servlet.
Here is the explanation :-

First and foremost lets know something about a filter. I believe everyone of us has seen a basic water filter. What does it do? Of course, it filters water so that we get pure and clean dringking water so that we can stay healthy. Similarly, when web applications were created, the developers presumably chose to use the same concept for web applications as well.

Just as in a normal water filter, a Filter in a web application in a piece of code that is supposed to execute when a client requests for a particular web resource. For example, in this application, the client will request for a servlet file, but before the code in the servlet file is executed, the code in the Filter will execute without the client being aware of this fact.

So, why do we use filters? Well, filters are intended to do important pre-processing of client requests. What kind of pre-processing? Well, normally, when we talk about pre-processing, we mean performing certain basic tasks that are not directly related to the client request. For example logging, authentication, authorization, encryption - decryption, data compression etc.

All these tasks are supposed to run without the client requesting for them directly. We also notice an important feature about these pre-processing tasks. Most of them will be required for a large number of resources in a web-application. For example, i may have 3 servlets in my application whcih may require encryption to be done. Since this is a common task, I can use an encryption filter in my web application and assiciate these servelts with the encryption filter. The advantage that i gain by doing this is that that encryption code that is common to all these three filters does not become redundant in the three servlets. MoreOver, if i later on need to extend my application, and have more servlets require the encryption filter, all that I have to do is to associate the new servlet with the filter thereby reducing development effort and time. Over and above, if the encryption algorithm need to be changed, then io need to make changes in only a single location and it will be automatically be reflected in all the servlets associated with the encryption filter.

Filters are used in web-application declaratively. This means that I just tell the web application, through an xml file that I want to associate a particular filter with the given request-URL or a servlet. This mysterious xml file is the same old web.xml that we use all along.

Here is how I do it :-

MyFilter.java
//------Start Of Source Code------
package examples;

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

public class MyFilter implements Filter
{
FilterConfig fc;

public void init(FilterConfig fc) throws ServletException
{
this.fc=fc;
}

public void doFilter(ServletRequest req,ServletResponse resp,FilterChain chain) throws ServletException, IOException
{
HttpServletRequest hreq=(HttpServletRequest)req;
HttpServletResponse hresp=(HttpServletResponse)resp;

PrintWriter pw=hresp.getWriter();
hresp.setContentType("text/html");

pw.write("inside filter, before going to the servlet");

chain.doFilter(req,resp);

pw.write("inside filter, after returning from the servlet");

pw.flush();
pw.close();
}

public void destroy()
{
}
}
//------End Of Source Code------



MyServlet.java
//------Start Of Source Code------
package examples;

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

public class MyServlet extends HttpServlet
{
public void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException
{
PrintWriter pw=resp.getWriter();

pw.write("<br/>");
pw.write("inside the servlet");
pw.write("<br/>");

}
}

//------End Of Source Code------



web.xml
//------Start Of Source Code------
<web-app>
<servlet>
<servlet-name>SampleServlet</servlet-name>
<servlet-class>examples.MyServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>SampleServlet</servlet-name>
<url-pattern>/go</url-pattern>
</servlet-mapping>

<filter>
<filter-name>SampleFilter</filter-name>
<filter-class>examples.MyFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>SampleFilter</filter-name>
<url-pattern>/go</url-pattern>
</filter-mapping>
</web-app>

//------End Of Source Code------


Compile the java files and copy the .class files obtained into the WEB-INF/classes/examples directory.
Now Start tomcat and type the following url in your address bar :-
http://localhost:8080/FilterExample/go
Now press the Enter/Return key.

You should get the following output :-
inside filter, before going to the servlet
inside the servlet
inside filter, after returning from the servlet

This is jsut a bare bones example do demonstrate how to use filters. Kindly ignore the malformed html. I have not followed any good programming practice just to keep the code as simple as possible and to focus on the problem at hand. Hope that you find this demonstration useful.

Happy Programming ;)

Signing Off
Ryan

No comments: