Synchronize session beans and filter

By , last updated July 21, 2019

One of the problems I’ve faced while creating a JEE application with Spring is how to access a session scoped data in our filters.

Suppose we have some custom UserFilter class:

package our.filters;

public class UserFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        if (request) {
            //.. do smth here
        }else{
            chain.doFilter(request, response);
        }
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }
}

Then our web.xml file will probably look like this:

    <filter>
        <filter-name>userFilter</filter-name>
        <filter-class> our.filters.UserFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>userFilter</filter-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </filter-mapping>

Now suppose we face a problem such that we need to access session data from our filter. In an applicationContext.xml file we add a bean definition with a sessionHandler:

    <bean id="userFilter"
        class="our.filters.userFilter">
        <property name="sessionHandler" ref="flexSessionHandler"/>
    </bean>

And of course we change our UserFilter class and add a session to it:

package our.filters;

public class UserFilter implements Filter {

    SessionHandler sessionHandler;

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        if (request && sessionHandler != null) {
            //.. do smth here
        }else{
            chain.doFilter(request, response);
        }
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }

   @Required
    public void setSessionHandler(SessionHandler sessionHandler) {
         this.sessionHandler = sessionHandler;
    }
}

Now we run the program … but it doesn’t work! Yeah, magically it appears to be two different instances of UserFilter class being created: one created by a bean and the other one by filter. To solve the problem we need both a filter and a bean to work with the same instance of UserFilter. To do that we need to change a filter-class parameter in web.xml to use DelegatingFilterProxy.

DelegatingFilterProxy delegates to a Spring-managed bean that implements the Filter interface. All calls to the filter proxy will then be delegated to the specified bean in the Spring context (JavaDoc).

So here is how web.xml will look like after all:

    <filter>
        <filter-name>userFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>userFilter</filter-name>
        <url-pattern>/messagebroker/*</url-pattern>
    </filter-mapping>

Senior Software Engineer developing all kinds of stuff.