Friday 15 June 2012

Filters in Java


  • Servlet filters are a new addition to the servlet 2.3 realized in Oct 2000
  • Definition:
    • Filters are java classes that can intercepts request from a client before they access a resource, manipulate request from clients, intercepts response from resource before they sent back to the client.
  • Filters have a wide array of uses; the Servlet 2.3 specification suggests the following uses:
    • authentication filters
    • logging and auditing filters
    • image conversion filters
    • data compression filters
    • encryption filters
    • tokenizing filters
    • filters that trigger resource access events
    • XSL/T filters that transform XML content
    • MIME-type chain filters





Writing a Simple Filter

The first step in learning how to write a filter is to look at a very simple example. A filter is simply a Java class that implements the javax.servlet.Filter interface. The javax.servlet.Filter interface defines three methods
  • public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain)
  • public FilterConfig getFilterConfig()
  • public void setFilterConfig (FilterConfig filterConfig)
  • It is the containers responsibility to create a javax.servlet.FilterConfig object and pass it to the filter during initialization. The javax.servlet.FilterConfig object can be used to
    • retrieve the filter name (as defined in the deployment descriptor),
    • retrieve the initial parameters (as defined in the deployment descriptor), and
    • get a reference to the ServletContext object the user is calling from
The setFilterConfig() method can be used to capture the object into an attribute of the filter. The doFilter() method is where the filter's work is done, in which you can parse the user's request; log statistics to a file; manipulate the response back to the client; and so on.

 Listing 1 is an example of a very simple filter which prints a message to the console of the web server while it is filtering the request, calls the Servlet, and then prints another message to the console while it is filtering the response. 

 above diagram of how the simple filter fits into the servlet's request-response model

Sample Program for Filters
servletex.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class servletex extends HttpServlet {
    public servletex() {
System.out.println("Servlet Object has been created");
    }
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("servlet method is executing");
PrintWriter pw=response.getWriter();
pw.println("<br>servlet method is executing<br>"); }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("servlet method is executing");
}
}

filter1.java


import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class SimpleFilter implements Filter {
    public SimpleFilter() {
            }
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try
   {
     System.out.print ("Within Simple Filter ... ");
     System.out.println ("Filtering the Request ...");
     PrintWriter pw=response.getWriter();
     pw.println("before filter");
     chain.doFilter (request, response);
     pw.println("<br>after fileter");
     System.out.print ("Within Simple Filter ... ");
     System.out.println ("Filtering the Response ...");

   } catch (IOException io) {
     System.out.println ("IOException raised in SimpleFilter");
   } catch (ServletException se) {
     System.out.println ("ServletException raised in SimpleFilter");
   }
}
public void init(FilterConfig fConfig) throws ServletException {
}

}

Web.xml

<web-app>
<servlet>
    <description></description>
    <display-name>simpleservelt</display-name>
    <servlet-name>simpleservelt</servlet-name>
    <servlet-class>simpleservelt</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>simpleservelt</servlet-name>
    <url-pattern>/simple</url-pattern>
  </servlet-mapping>
  <filter>
    <display-name>SimpleFilter</display-name>
    <filter-name>SimpleFilter</filter-name>
    <filter-class>SimpleFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>SimpleFilter</filter-name>
    <url-pattern>/simple</url-pattern>
  </filter-mapping>
</web-app>


Filters with JSP

Logging.jsp

<%@ page language="java" %>
 <html>
   <head>
   <title>Logging Filter Example</title>
   </head>
  <body>
  <h1>Logging Filter</h1>
  This filter writes log file of Tomcat Web Server.
  <hr>
   See log file of Web server.
  <br>
 
  </body>
  <%
  System.out.println("jsp program is executing");
 
  %>
</html>



LoggingFilterExample.java

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

public final class LoggingFilterExample implements Filter
{
  private FilterConfig filterConfigObj = null;
  public void init(FilterConfig filterConfigObj) {
  this.filterConfigObj = filterConfigObj;
  System.out.println("init method of filter is executed");
  }

  public void doFilter(ServletRequest request,
ServletResponse response,
  FilterChain chain)
  throws IOException, ServletException
  {
                         
 System.out.println("servlet program is being executed");
  String remoteAddress =  request.getRemoteAddr();
  String uri = ((HttpServletRequest) request).getRequestURI();
  String protocol = request.getProtocol();
  chain.doFilter(request, response);
  System.out.println("servelt program is executed");
  }
  public void destroy() {
                          System.out.println("destory method is executed");
  }
}


Web.xml
<web-app>
<display-name>Welcome to Tomcat</display-name>
  <description>Welcome to Tomcat</description>
  <filter>
   <filter-name>LoggingFilterExample</filter-name>
  <filter-class>LoggingFilterExample</filter-class>
  </filter>
  <filter-mapping>
  <filter-name>LoggingFilterExample</filter-name>
  <url-pattern>/logging.jsp</url-pattern>
  </filter-mapping>
</web-app>


Filter Chaining

In the first example only one filter that handled the request and response for the simple servlet. What if you want multiple filters to handle the request and response? 


Filter1.java

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.IOException;
import javax.servlet.ServletException;
public class Filter1 implements Filter
{
  private FilterConfig filterConfig;

  public void doFilter (ServletRequest request,
              ServletResponse response,
              FilterChain chain)
  {

    try
    {
      System.out.print ("Within First Filter ... ");
      System.out.println ("Filtering the Request ...");
      chain.doFilter (request, response);
      System.out.print ("Within First Filter ... ");
      System.out.println ("Filtering the Response ...");
    } catch (IOException io) {
      System.out.println ("IOException raised in Filter1 Filter");
    } catch (ServletException se) {
      System.out.println ("ServletException raised in Filter1 Filter");
    }
  }
  public FilterConfig getFilterConfig()
  {
    return this.filterConfig;
  }
  public void setFilterConfig (FilterConfig filterConfig)
  {
    this.filterConfig = filterConfig;
  }
}



Filter2.java


import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import java.io.IOException;
import javax.servlet.ServletException;

public class Filter2 implements Filter
{
  private FilterConfig filterConfig;

  public void doFilter (ServletRequest request,
              ServletResponse response,
              FilterChain chain)
  {

    try
    {
      System.out.print ("Within Second Filter ... ");
      System.out.println ("Filtering the Request ...");

      chain.doFilter (request, response);

      System.out.print ("Within Second Filter ... ");
      System.out.println ("Filtering the Response ...");

    } catch (IOException io) {
      System.out.println ("IOException raised in Filter2 Filter");
    } catch (ServletException se) {
      System.out.println ("ServletException raised in Filter2 Filter");
    }
  }
  public FilterConfig getFilterConfig()
  {
    return this.filterConfig;
  }

  public void setFilterConfig (FilterConfig filterConfig)
  {
    this.filterConfig = filterConfig;
  }
}



SimpleServlet.java

Public class SimpleServlet implements HttpServlet
{
//logic
}

Web.xml

<web-app>
  <filter>
    <filter-name>
      First Filter in Chain
    </filter-name>
    <filter-class>
      com.filters.Filter1
    </filter-class>
  </filter>

  <filter>
    <filter-name>
      Second Filter in Chain
    </filter-name>
    <filter-class>
      com.filters.Filter2
    </filter-class>
  </filter>
  <filter-mapping>
    <filter-name>
      First Filter in Chain
    </filter-name>
    <url-pattern>
      /simple
    </url-pattern>
  </filter-mapping>

  <filter-mapping>
    <filter-name>
      Second Filter in Chain
    </filter-name>
    <url-pattern>
      /simple
    </url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>
      Simple Servlet
    </servlet-name>
    <servlet-class>
      com.servlets.SimpleServlet
    </servlet-class>



Parsing a User's Request and Using Initial Parameters

So far the examples of the filters have been trivial. Now it's time to do something more realistic. Sometimes you may want to use a filter to verify certain objects pass with the requests, such as elements from an HTML form. You may want to verify the existence and validity of the values. If they don't exist, you send the client's request to one servlet. If they do exist but the values are not valid, then they are sent to a different servlet. Finally, if the elements check out, they are passed to the requested servlet. Figure 6 shows a diagram of this scenario.


Let's take this example one step further. Not only do we want to verify HTML form data, we want to retrieve the names of the HTML form elements from initialization parameters. This means that if the HTML form changes, we do not need to change any code in the filter; we simply change the initialization parameters for the filter.

Initialization parameters can be specified in the deployment descriptor. They are specified when the filter is defined. Listing 6 is the code for the filter that retrieves HTML form element names from initialization parameters, verifies the form data, and sends the request to the appropriate servlet.

Filter1.java
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.RequestDispatcher;

import java.util.Enumeration;

import java.io.IOException;
import javax.servlet.ServletException;

public class filter1 implements Filter
{
  private FilterConfig filterConfig;

  public void doFilter (ServletRequest request,
              ServletResponse response,
              FilterChain chain)
  {

    RequestDispatcher rd = null;
    boolean emptyform = false;

    try
    {

      Enumeration initParams = filterConfig.getInitParameterNames();

      // no initial parameters so invoke next element in chain
      if (initParams == null)
      {
        System.out.println("No elements to verify");
        chain.doFilter(request, response);
      }

      // grab init param values and get the form elements
      else
      {
        while (initParams.hasMoreElements())
        {
          String name = (String) initParams.nextElement();
          String value = filterConfig.getInitParameter(name);

          String formElement = request.getParameter(value);

          // check to see if element exists (i.e. form was sent)
          if (formElement == null)
          {
            rd = request.getRequestDispatcher("/noform");
            rd.forward(request, response);
          }

          // check to see if elements are empty
          else if (formElement.equals(""))
          {
            emptyform = true;
          }
        }

        // a form element was empty
        if (emptyform)
        {
          rd = request.getRequestDispatcher("/emptyform");
          rd.forward(request, response);
        }

        // form was filled out properly
        else
        {
          chain.doFilter(request, response);
        }
      }
    }
    catch (IOException io)
    {
      System.out.println("IOException raised");
    }
    catch (ServletException se)
    {
      System.out.println("ServletException raised");
    }

  }

  public FilterConfig getFilterConfig()
  {
    return this.filterConfig;
  }

  public void setFilterConfig (FilterConfig filterConfig)
  {
    this.filterConfig = filterConfig;
  }
}



web.xml

<web-app> <filter>
    <filter-name>
      Parsing Request Data
    </filter-name>
    <filter-class>
      com.filters.RequestFilter
    </filter-class>

    <init-param>
      <param-name>
        User's Name
      </param-name>
      <param-value>
        myname
      </param-value>
    </init-param>

    <init-param>
      <param-name>
        User's Email
      </param-name>
      <param-value>
        txtemail
      </param-value>
    </init-param>
  </filter>


  <!-- Map the filter to a Servlet or URL -->

  <filter-mapping>
    <filter-name>
      Parsing Request Data
    </filter-name>
    <url-pattern>
      /formprocessor
    </url-pattern>
  </filter-mapping>



  <!-- Define the Servlets within the Web Application -->

  <servlet>
    <servlet-name>
      No Form Submitted
    </servlet-name>
    <servlet-class>
      com.servlets.NoElements
    </servlet-class>
  </servlet>

  <servlet>
    <servlet-name>
      Empty Form Elements
    </servlet-name>
    <servlet-class>
      com.servlets.InvalidEntries
    </servlet-class>
  </servlet>

  <servlet>
    <servlet-name>
      Good Request
    </servlet-name>
    <servlet-class>
      com.servlets.MyServlet
    </servlet-class>
  </servlet>


  <!-- Define Servlet mappings to urls -->

  <servlet-mapping>
    <servlet-name>
      No Form Submitted
    </servlet-name>
    <url-pattern>
      /noform
    </url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>
      Empty Form Elements
    </servlet-name>
    <url-pattern>
      /emptyform
    </url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>
      Good Request
    </servlet-name>
    <url-pattern>
      /formprocessor
    </url-pattern>
  </servlet-mapping>

</web-app>





No comments:

Post a Comment