11

I'm trying to inject a spring bean into a filter, but can't make it work.

The bean injected is always "null". I succeed autowiring this same bean in Controllers and HandlerInterceptors so it's correctly annotated.

The filter class is under the same base-package of the rest of Controllers.

This is the relevant part of my web.xml

  <filter>
    <filter-name>CheckSession</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>CheckSession</filter-name>
    <url-pattern>/panel/*</url-pattern>
  </filter-mapping>

This is the code for the filter

@Component 
public class CheckSession extends OncePerRequestFilter implements Filter {

    @Autowired private Usuario usuario;

    @Override
    protected void doFilterInternal(
        HttpServletRequest request,
        HttpServletResponse response, FilterChain chain)
    throws ServletException, IOException {

        //  always null
        System.out.println("autowired " + usuario);
        chain.doFilter(request,  response);
    }
}

The filter is triggering on every request.

These are the annotations in the "Usuario" bean

@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class Usuario implements java.io.Serializable { ... }

What am i missing? Thanks!

Vikdor
  • 23,934
  • 10
  • 61
  • 84
metacortechs
  • 141
  • 1
  • 1
  • 6
  • Shouldn't you use your exact class name in 'filter-class'? And are you sure your filter is managed by Spring? Shouldn't you use @Configurable here? – skegg99 Mar 13 '12 at 21:07
  • The filter's name is CheckSession, the same as indicated in "filter-name". If i change that name in "filter-name" I get a "NoSuchBeanDefinitionException" from Spring. So i guess yes, the filter is being managed by Spring (through DelegatingFilterProxy) but the autowire mechanism still isn't working... :( – metacortechs Mar 13 '12 at 21:51

2 Answers2

9

Try to explicitly define the name for your CheckSession bean and see if that helps... Like this:

@Component("CheckSession")
public class CheckSession extends OncePerRequestFilter implements Filter {
    @Autowired private Usuario usuario;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        //  always null
        System.out.println("autowired " + usuario);
        chain.doFilter(request,  response);
    }
}

The key part is this: @Component("CheckSession")

And to make things prettier and easier to deal with down the road, I would camelCase the name and rename it to "checkSession" everywhere (de-capitalize first letter).

anton1980
  • 979
  • 3
  • 10
  • 20
7

Works on Spring 3.2.6:

First: Name your component, 2 options - do only one

Option A: Annotation - assumes component scanning enabled

@Component("checkSession")
public class CheckSession extends OncePerRequestFilter {

@Autowired 
Usuario usuario;

@Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws ServletException, IOException {

    // not null
    System.out.println("autowired " + usuario);
    chain.doFilter(request,  response);
    }
}

Option B: wire bean via appliationContext.xml

<bean id="checkSession" class="com.example.filter.CheckSession"></bean>

Second: Wire up Spring DelegatingFilterProxy

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

<filter-mapping>
  <filter-name>checkSession</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Notes: the bean name is referenced as the filter-name

jurassix
  • 1,509
  • 10
  • 10