Show TOC Start of Content Area

Process documentation Filtering Requests or Responses  Locate the document in its SAP Library structure

Purpose

Filters execute their logic, which affects the follow-on request processing in their doFilter() method. This method gets the request and response objects, and a FilterChain object as parameters (the request and response objects are of type javax.servlet.ServletRequest and javax.servlet.ServletResponse, respectively).

Using the doFilter() method of the FilterChain object, you invoke the next filter in the chain. The order of invocation of filters in the chain is determined by the order, in which you have declared filter classes in the deployment descriptor of the Web application.

Process Flow

Since there are a lot of options for modifying the request or the response in your filter, and each option depends on the specific functions that the filter is performing, we will give you a few hints on what you can do in the doFilter() method of your filters:

·        You can override the response or the request objects using the ServletReponseWrapperor ServletRequestWrapper objects. You can then pass the overridden objects as parameters of the FilterChain.doFilter() method, and have the next component in the chain work on them. This approach is suitable for filters that compress responses, any type of data conversion or encryption, and so on.

Example

Here is an example of a filter that modifies the response that a servlet generated. It is called a StyleFilter and it inserts the title of an HTML page as well as the HTML table that the servlet generates. The servlet sets the title of the page as an attribute of the request object and the filter retrieves it using the request.getAttribute()method. Here is the doFilter() method of the StyleFilter:

public void doFilter(

         ServletRequest _request,

         ServletResponse response,

         FilterChain chain)

         throws IOException, ServletException {

       HttpServletRequest request = (HttpServletRequest)_request;

       ServletOutputStream out = response.getOutputStream();

       String contextRoot = request.getContextPath();

       out.println("<HTML>");

       out.println("<HEAD>");

       out.println("<link rel='stylesheet' type='text/css' href='" + contextRoot + "/style.css'>");

       out.println("<TITLE>");

       FilterResponseWrapper wrapper = new FilterResponseWrapper((HttpServletResponse)response);

       chain.doFilter(request, wrapper);

       out.println("Title from servlet: " + request.getAttribute("title"));

       out.println("</TITLE>");

       out.println("</HEAD>");

       out.println("<BODY>");

       doSourceFiles(out, contextRoot);

       out.write(wrapper.getData());

       out.println("</BODY>");

       out.println("</HTML>");

     }

Since this filter modifies the response object, it must seize the response before it is returned to the client. To do this, the StyleFilter passes a stand-in stream to the servlet that prevents it from closing the response stream. Technically, this stand-in stream is done by providing a custom response wrapper that overrides the getWriter and the getOutputStreammethods of the original response. To provide the response wrapper, the StyleFilter uses the FilterResponseWrapper object that extends the HttpServletResponseWrapper class and overrides the getWriter and getOutputStream methods in its body. Here is the code of the FilterResponseWrapperclass:

public class FilterResponseWrapper extends HttpServletResponseWrapper {

  

   FilterOutputStream out = null;

   public FilterResponseWrapper(HttpServletResponse response) {

      super(response);

      out = new FilterOutputStream();

   }

  

   public ServletOutputStream getOutputStream() {

     return out;

   }

  

   public PrintWriter getWriter() {

     return new PrintWriter(out, true);

   }

  

   public byte[] getData() {

      return out.getData();

   }

 

}

·        You can have a filter that examines the attributes of the request, and based on this, it determines whether to call the next component in the chain, or to redirect the user to a specific page, for example. This is the case for filters that perform user authorization checks and either let the request be processed, or redirect the client to a login page.

Example

The SecurityFilter is an example of such a filter that checks the security principal of the user, and passes the request to the next component in the chain if the client is authorized, or blocks it and returns an error message to the client if it is not authorized. Here is the doFilter() method of the filter:

public void doFilter(

      ServletRequest _request,

      ServletResponse _response,

      FilterChain chain)

      throws IOException, ServletException {

      HttpServletRequest request = (HttpServletRequest)_request;

      HttpServletResponse response = (HttpServletResponse)_response;

      Principal principal= request.getUserPrincipal();

      if (checkPrincipal(principal)){

         request.setAttribute("principal", "Successfully authorized");

         chain.doFilter(request, response); 

      } else {

         response.sendError(HttpServletResponse.SC_UNAUTHORIZED);

      }

   }

Furthermore, you must define a public boolean checkPrincipal(Principal principal) method in the filter class that is used to perform the security check in the doFilter() method.

·        You can have a filter that keeps track of requests to certain resources and logs statistical information such as the number of hits to the resource, the request processing time, and so on.

Example

The LogFilter is an example of this type of filter. It measures the time for which the request is processed and prints it to system output. Here is the doFilter() method of the filter:

public void doFilter(

      ServletRequest request,

      ServletResponse response,

      FilterChain chain)

      throws IOException, ServletException {

      long start = System.currentTimeMillis();

      request.setAttribute("time", new java.util.Date(start));

      chain.doFilter(request, response); 

      long end = System.currentTimeMillis();

      log(end - start);

   }

In addition, you must define a public void log(long time) method in the filter class that prints the request processing time.

Note

The filter classes we presented above are part of the Servlet Filter example application, which is part of the J2EE Engine default application. You can review the full code of the classes, and test the functions of the filters.

 

 

End of Content Area