Search This Blog

Friday, 26 July 2013

Filters and Spring

I guess we have all used filters in our web applications. With the arrival of spring and its very solid front controller, code that was in filters is most of the time placed in Spring interceptors. But that does not mean that we cannot add a filter.
We can still define custom filters and work with them. But - and this is a big but - a normal filter
runs outside the Spring world. It has no awareness of beans, context etc.
Can we bring the two together ? Yes, spring does provide integration for the same.
The most basic class provided by Spring is the GenericFilterBean:
From the java docs
Simple base implementation of javax.servlet.Filter that treats its config parameters 
as bean properties. Unknown parameters are ignored. A very handy superclass for any 
type of filter.
Accordingly I decided to create a simple logging filter.
Step 1 was to define the code for the filter:
public class AuditRequestFilter extends GenericFilterBean {
   @Override
   public void doFilter(final ServletRequest request,
         final ServletResponse response, final FilterChain filterChain)
         throws IOException, ServletException {
      final HttpServletRequest httpRequest = (HttpServletRequest) request;
      final HttpServletResponse httpResponse = (HttpServletResponse) response;
      System.out.println("request is " + httpRequest.getClass());
      System.out.println("request URL : " + httpRequest.getRequestURL());
      System.out.println("response is " + httpResponse.getClass());
      filterChain.doFilter(request, response);
   }
}
The filter does nothing - It prints the request and response to the Console. Step 2 was to set the configuration in the web.xml.
   <filter>
      <filter-name>simpleFilter</filter-name>
      <filter-class>com.filter.AuditRequestFilter</filter-class>
   </filter>

   <filter-mapping>
      <filter-name>simpleFilter</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
It is like any other filter. On running the code the console displays the output:
request is class org.apache.catalina.connector.RequestFacade
request URL : http://localhost:8080/SpringFilter/
response is class org.apache.catalina.connector.ResponseFacade
As per the documentation, any init param will be converted to an instance member of the filter if present (if such a editor is available). So I added an init param:
      <init-param>
         <param-name>id</param-name>
         <param-value>109</param-value>
      </init-param>
The filter definition was modified to:
public class AuditRequestFilter extends GenericFilterBean {
   private int id;
   //setter getters and code
}
Running the code indicated that the values were set.
What if we want to access beans here?
Consider the simple bean definition:
   <bean id="simpleBean" class="java.lang.String">
      <constructor-arg value="HelloBean"></constructor-arg>
   </bean>
This creates a simple string. I placed the bean definition in a file that was loaded as a part of the root context.
  <context-param>
    <description>Spring context configuration location</description>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:common-config.xml</param-value>
  </context-param>
  <listener>
    <display-name>ContextLoaderListener</display-name>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
The filter ( or any normal filter) has access to the ServletContext. The following code gives us access to the bean:
private void displayMessage() {
      final WebApplicationContext applicationContext = WebApplicationContextUtils
            .getWebApplicationContext(this.getServletContext());
      System.out.println(applicationContext.getBean("simpleBean"));
   }
The logs indicate the output:
DEBUG DefaultListableBeanFactory:246 - Returning cached instance of singleton bean 'simpleBean'
HelloBean
Thus the filter is capable of accessing beans created in the root web Application context.  
The GenericFilterBean class is on the hierarchy of most(maybe all) filters defined in Spring (check the org.springframework.web.filter package). Even Spring security filters have it in their hierarchy.

2 comments:

  1. Why do people mention filters more in context of Spring security?

    https://emerging-teks.blogspot.com

    ReplyDelete
  2. Your knowledge is really helpful.
    Please keep it up :)

    ReplyDelete