Java Servlet Filters.

Using Filters with Servlets

  • A filter is an object that performs filtering tasks either on the request to a resource, or on the response from a resource, or both.
  • Filters are used for several purpose which could be:
    • Authentication filters.
    • Logging and auditing filters.
    • Data compression filters.
    • Encryption filters.
    • Tokenizing Filters.
    • Filters that trigger resource access events.
  • When encapsulating common functionality in a filter, the same filter can easily be used with several servlets.

The Filter API

  • The Filter API consists of three interfaces:
    1. javax.servlet.Filter
    2. javax.servlet.FilterChain
    3. javax.servlet.FilterConfig
    Methods in javax.servlet.Filter interface:
    Method Description
    public void init(FilterConfig filterConfig) Called by the web container to indicate to a filter that it is being placed into service.
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) The doFilter() method is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain.
    public void destroy() Called by the web container to indicate to a filter that it is being taken out of service.
  • To create a filter class you must implements the javax.servlet.Filter interface to the class and implement codes for alle the above methods.
  • The javax.servlet.FilterConfig interface is an argument to the init() method.
  • The Container gives us through this interface some information about initial parameters and access to the ServletContext as well.
  • Methods in javax.servlet.FilterConfig interface:
    Method Description
    public String getFilterName() Returns the filter-name of this filter as defined in the deployment descriptor.
    public ServletContext getServletContext() Returns a reference to the ServletContext in which the caller is executing.
    public String getInitParameter(String name) Returns a String containing the value of the named initialization parameter, or null if the parameter does not exist.
    public Enumeration getInitParameterNames() Returns the names of the filter's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the filter has no initialization parameters.
  • The javax.servlet.FilterChain interface is an argument to the doFilter() method. This interface has only one method, doFilter(), which are used by the programnmer to causes the next filter in the chain to be invoked. Methods in javax.servlet.FilterChain interface:
    Method Description
    public void doFilter(ServletRequest request, ServletResponse response) Causes the next filter in the chain to be invoked, or if the calling filter, is the last filter in the chain, causes the resource at the end of the chain to be invoked.
    The chain could be like this:
  • The deployment descriptor is used to tell the container which, if any, filters in which sequence to call for each servlet in the application.

Example of a simple Servlet program with two Filters.

As selected we use Netbeans IDE and Glassfish Server.

You can download this example here (needed tools can be found in the right menu on this page).

If you like to participate in the review of this example you must first create a Web project in Netbeans (the project name is ServletFilter).

  • We start with the Login servlet:
    package web;
    
    import java.io.PrintWriter;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class Login extends HttpServlet {
    
      @Override
      public void doPost(HttpServletRequest request,
              HttpServletResponse response) {
    
        System.out.println("Start doPost in Login");
        String username = request.getParameter("username");
        try {
          response.setContentType("text/html");
          PrintWriter writer = response.getWriter();
          writer.println("<html><body>");
          writer.println("Thank you, " + username
                  + ". You are now logged into the system.");
          writer.println("</body></html>");
          writer.close();
          System.out.println("End doPost in Login");
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }

    For those who participate in the review: create a Servlet in Netbeans and replace generated code for the servlet with that shown above (the servlet name is Login).

  • Servlet expect to get a POST type of request that has been handled by filters before this servlet.
  • We set the Content type to "text/html" for the response to the client (browser) and use a PrintWriter on the response object to return text and html codes back to the client.
  • We fetch the username from the request parameter, create some html code and text, include the username, and return all as a response.
  • All filters in front will handle the response before it is delivered to the client (browser).
    Here is the second filter, LogB, which is the last filter before the servlet:
    package web;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    
    public class LogB implements javax.servlet.Filter {
    
      @Override
      public void init(javax.servlet.FilterConfig filterConfig) {}
    
      @Override
      public void doFilter(javax.servlet.ServletRequest request,
                           javax.servlet.ServletResponse response,
                           javax.servlet.FilterChain chain)
      {
        System.out.println("Entered LogB doFilter()");
        System.out.println("protocol is " + request.getProtocol());
        System.out.println("remote host is " + request.getRemoteHost());
        System.out.println("content type is " + request.getContentType());
        System.out.println("content length is " + request.getContentLength());
        System.out.println("username is " + request.getParameter("username"));
    
        try {
        // To call the Servlet in the chain we use the doFilter() method. 
          chain.doFilter(request, response);
        // We will now have information in response object provided by the servlet.
        } catch (IOException e) {
          e.printStackTrace();
        } catch (ServletException e) {
          e.printStackTrace();
        }  
      }
    
      @Override
      public void destroy() {
      }
    }

    For those who participate in the review: create a Filter in Netbeans and replace generated code for the filter with that shown above (the filter name is LogB).

  • The Web container starts to call the init() method when it is created and then call the doFilter() for any request.
  • We prints on the Server log some information about data received through the request object.
  • To call the Servlet in the chain we use the doFilter() method that exists in the FilterChain interface. The ServletRequest interface reference and the ServletResponse interface reference are passed to this method.
  • When the method is carried out, we will have information in response object provided by the servlet.
    Filtering starts with the LogA filter:
    package web;
    
    import java.io.IOException;
    import javax.servlet.ServletException;
    
    public class LogA implements javax.servlet.Filter {
    
      private javax.servlet.ServletContext context;
    
      @Override
      public void init(javax.servlet.FilterConfig filterConfig) {
        context = filterConfig.getServletContext();
      }
    
      @Override
      public void doFilter(javax.servlet.ServletRequest request,
              javax.servlet.ServletResponse response,
              javax.servlet.FilterChain chain) {
        System.out.println("LogA passing request to next filter");
        try {
          chain.doFilter(request, response);
        } catch (IOException e) {
          e.printStackTrace();
        } catch (ServletException e) {
          e.printStackTrace();
        }
        System.out.println("The servlet has finished processing the request");
        System.out.println("LogA filter is now working to process the response");
      }
    
      @Override
      public void destroy() {
      }
    }

    For those who participate in the review: create a Filter in Netbeans and replace generated code for the filter with that shown above (the filter name is LogA).

  • The Web container starts to call the init() method when it is created and then call the doFilter() for any request.
  • We prints on the Server log some information.
  • We could of course add or change some information in the ServletRequest interface as an verification to succeeding filter or servlet, but for now we do nothing.
  • To call the logB filter in the chain we use the doFilter() method that exists in the FilterChain interface. The ServletRequest interface reference and the ServletResponse interface reference are passed to this method.
  • When the method is carried out, we will have information in response object provided by the servlet and the LogB filter.
    The html startup file, login.html, for the browser can be like this:
    <!DOCTYPE HTML>
    <html>
      <head>
        <title>Login</title>
      </head>
      <body>
        <h1>Login</h1>
       Please enter your username and password
        <form action="/ServletFilter/Login" method="POST">
          <p><input type="text" name="username" style="width: 100px;">
          <p><input type="password" name="password" style="width: 100px;">
          <p><input type="submit" value="Submit">
        </form>
      </body>
    </html>

    For those who participate in the review: create a HTML page in Netbeans and replace generated code for the html file with that shown above (the name of the html should be login and places in the folder web).

Creating Deployment descriptor.

  • To run this Servlet with filters you have to deploy it to a web-server or a Application server. To deploy means to install the Servlet and Filters with some instruction to a such server.
  • The instructions are mainly defined to be deployment descriptors. The standard part of the deployment descriptor should be in an XML-file with the name web.xml. In the later version of java it is possible to specify this in the form of annotations in front of the Servlet.

    You may need to create a Deployment descriptor file, web.xml in Netbeans.

  • The contents of the web.xml file regarding servlet and Filters should look like this:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
    http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        <filter>
            <filter-name>LogB</filter-name>
            <filter-class>web.LogB</filter-class>
        </filter>
        <filter>
            <filter-name>LogA</filter-name>
            <filter-class>web.LogA</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>LogA</filter-name>
            <servlet-name>Login</servlet-name>
        </filter-mapping>
        <filter-mapping>
            <filter-name>LogB</filter-name>
            <servlet-name>Login</servlet-name>
        </filter-mapping>
        <servlet>
            <servlet-name>Login</servlet-name>
            <servlet-class>web.Login</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>Login</servlet-name>
            <url-pattern>/Login</url-pattern>
        </servlet-mapping>
      <session-config>
        <session-timeout>
          30
        </session-timeout>
      </session-config>
      <welcome-file-list>
        <welcome-file>login.html</welcome-file>
      </welcome-file-list>
    </web-app>
  • This file starts with the normal xml tag for a XML file and the root tag for the deployment descriptor is web-app. Every ting inside the last tag is to tell the server about our application, which in this case is a Servlet.
  • With a servlet tag we give the Servlet class a servlet name, which is used in the servlet-mapping tag to specify a url for the Servlet.
  • In this way we can have many urls for the same servlet.
  • It is the sequence of the filter-mapping tags that decides the chain - not the filter tags
  • If no session-timeout (the server ends the service of the application after this time) is given a standard timeout for the server is used as timeout for the application.
  • The welcome-file tag specifies the startup for our application, which in this case and our application is the welcome file login.html. Reorganize the welcome-file-list to what is shown above.

Creating Web-server Deployment descriptor.

  • The context-root (in example /ServletFilter) for the application will in most cases be specified by a server vendor deployment descriptor.

    For those who participate in the review: create a deployment descriptor in Netbeans.

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, 
    Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN" 
    "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
    <sun-web-app error-url="">
      <context-root>/ServletFilter</context-root>
      <class-loader delegate="true"/>
      <jsp-config>
        <property name="keepgenerated" value="true">
          <description>
            Keep a copy of the generated servlet class' java code.
          </description>
        </property>
      </jsp-config>
    </sun-web-app>

Run the application.

  • For those who participate in the review: right click the Web-project and select Run.
  • This results in that the application will be deployed to the server and started.
  • The browser will display:

    Login

    Please enter your username and password

    Enter a text, select some options and press the submit button.

    The result back to the browser from the Servlet should be something like:
    Thank you, Admin. You are now logged into the system.
    To show what is going on you must look at the server log file.
© 2010 by Finnesand Data. All rights reserved.
This site aims to provide FREE programming training and technics.
Finnesand Data as site owner gives no warranty for the correctness in the pages or source codes.
The risk of using this web-site pages or any program codes from this website is entirely at the individual user.