19

In my filter bean class, I added some beans dependency (with @Autowired annotation). But in the method doFilter(), all my dependency beans have null ...

public class FacebookOAuth implements Filter
{
@Autowired
private BusinessLogger logger;

@Autowired
private IUserSessionInfo userSessionInfo;

@Autowired
private FacebookOAuthHelper oAuthHelper;

public void init(FilterConfig fc) throws ServletException
{
    // Nothing to do
}

public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws   IOException, ServletException
{
    // HttpServletRequest req = (HttpServletRequest)sr;
    HttpServletResponse res = (HttpServletResponse) sr1;

    String code = sr.getParameter("code");

    if (StringUtil.isNotBlankStr(code))
    {
        String authURL = this.oAuthHelper.getAuthURL(code);

this.oAuthHelper is equal at null (and other dependancy beans to) ...

Could you help me ?


In fact I don't use MVC notion on server side (Spring). For my side client I use Flex technology and BlazeDS servlet ton communicate with my server.

So, that is the reason, I use the Filter bean notion.

So, how can I handle my session bean notion in my Filter bean ?


Skaffman,

I implemented your idea, so I update my application.xml with :

<bean id="FacebookOAuthHandler" class="com.xx.FacebookOAuthHandler" />
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
    <props>
       <prop key="/fbauth">FacebookOAuthHandler</prop>         
    </props>
   </property>
</bean>

and my FacebookOAuthHandler class :

public class FacebookOAuthHandler extends AbstractController
{
@Autowired
private BusinessLogger logger;

@Autowired
private IUserSessionInfo userSessionInfo;

@Autowired
private FacebookOAuthHelper oAuthHelper;

@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request,
        HttpServletResponse response) throws Exception {

    // TODO

    return null;
}

But, this method handleRequestInternal is never called when my URL is : http://xx.xx.xx.xx/MyApp/fbauth

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Anthony
  • 201
  • 1
  • 2
  • 4

5 Answers5

34

I was facing the same problem and my first idea was to manually force Spring to apply @Autowired annotation to the filter like proposed here

http://forum.springsource.org/showthread.php?60983-Autowiring-the-servlet-filter

But I don't like the idea of hardcoding the bean name in my Java class.

I found an cleaner way that works as well:

public void init(FilterConfig filterConfig) throws ServletException {
    SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,
            filterConfig.getServletContext());
}
Mathias G.
  • 4,875
  • 3
  • 39
  • 60
  • The reference is dead. The whole forum was closed in 2019. Have you an active reference. please? – Gangnus Nov 06 '20 at 13:04
13

Assuming this Filter is wired up in your web.xml, then this isn't going to work, since it's not managed by Spring, it's managed by the servlet container. So things like autowiring won't work.

If you want to define a servlet filter as Spring bean, then you need to define it in the webapp's root application context (using a ContextLoaderListener in web.xml), and then defining a DelegatingFilterProxy which delegates to your Spring-managed bean to do the work.

However, do you really need a servlet filter for this? What what I know of Facebook auth stuff, this could be done just as easily with a Spring HandlerInterceptor. This would be considerably less configuration work than a delegating filter.

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • Hi Skaffman ! Thanks a lot for your answer. Yeah, all my configuration files (web.xml, and my application.xml) are ok (with ContextLoaderListenner, with delegatingFilterProxy, etc.). But, even with this configuration, I can't used bean in my filter, that's right ? – Anthony Sep 05 '10 at 11:06
  • Can you please give some code examples how to define a servlet filter as a spring bean? – Dejell Aug 20 '13 at 13:41
  • I actually saw http://pro-programmers.blogspot.co.il/2011/08/spring-bean-as-servlet-filter.html article, but I am not using SpringMCV. will it help? – Dejell Aug 20 '13 at 14:07
  • The 1st paragraph is very interesting. The 2nd one says nothing about how to define something using CLL, and nothing about how to define and how to delegate by DFP. The third paragraph has the same problems. How the HI can serve as a filter? How and where should it be registered? References given are useless - they are simple links to docs, that we could easily google ourselves by the name of the class. And there are no answer to any questions mentioned. So, the answer is rather empty. – Gangnus Nov 06 '20 at 12:54
7

Look at this answer on site of spring: http://forum.springsource.org/showthread.php?60983-Autowiring-the-servlet-filter

In brief - you can manually force spring to apply @Autowire annotation to your filter:

public void init(FilterConfig filterConfig) throws ServletException {

    ServletContext servletContext = filterConfig.getServletContext();
    WebApplicationContext webApplicationContext = 
            WebApplicationContextUtils.getWebApplicationContext(servletContext);

    AutowireCapableBeanFactory autowireCapableBeanFactory =
           webApplicationContext.getAutowireCapableBeanFactory();

    autowireCapableBeanFactory.configureBean(this, BEAN_NAME);
}
Dewfy
  • 23,277
  • 13
  • 73
  • 121
7

I know it a now old question, but there is no example of usage of DelegatingFilterProxy in current responses, and one recent question asking for such an example was marked as a duplicate for this one.

So a DelegatingFilterProxy is a special filter that knows about root ApplicationContext and delegates its doFilterto a bean.

Example : MyFilter is a class implementing Filter, and myFilter is a spring bean

<bean id=myFilter class="org.example.MyFilter ...>...</bean>

or in a configuration class

@Bean
public MyFilter myFilter() {
    MyFilter myFilter = new MyFilter();
    //initialization ...
    return myFilter;
}

In web.xml, you just declare a DelegatingFilterProxy with same name as the bean :

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

That way, as myBean is a true bean, it can be injected normally with other beans with @Autowired annotations, and its doFilter method will be called by the DelegatingFilterProxy. As you can use spring init and destroy methods, by default init and destroy methods will not be called, unless you specify the "targetFilterLifecycle" filter init-param as "true".

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • I'm trying to do it in my project, but at server start, an error is thrown: Severe: Exception starting filter myFilter org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myFilter' is defined. I've tried to configure through either XML and Annotation. It seems that web.xml is read before bean is configured. – Alex Oct 03 '14 at 12:39
  • I used it in many projects, and never had any problem. But the bean must be declared in root context, not in dispatcher-servlet one. You should show how you declare you bean. – Serge Ballesta Oct 03 '14 at 13:03
  • I'm sorry for my rookiness, but how can I declare a bean either in root or dispatcher-servlet context? I have just created a configuration class in which I have put a "@Configuration" annotation, an then created a "@Bean" (refering to myFilter class). – Alex Oct 03 '14 at 14:17
  • @Alex Ok, so it should be in root context. Is the remaining of Spring configuration working correctly, an how is it declared ? – Serge Ballesta Oct 03 '14 at 14:36
  • Yes, it is. My only trouble is on filter stuff. I don't know wether the package where configuration class is matters (I don't think so), but is there a kind of configuration in order to set it into root context? – Alex Oct 03 '14 at 15:20
  • 1
    @Alex : what matters is that the package is scanned ... in any doubt, put the configuration class in a package where you have other configuration classes that are correctly processed. – Serge Ballesta Oct 03 '14 at 15:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/62418/discussion-between-serge-ballesta-and-alex). – Serge Ballesta Oct 03 '14 at 15:34
  • Yes, I did it. Actually, for test purposes, I put myFilter bean in the very class where I'm configuring sessionFactory (which is actually working fine). And it have not been configured. But note that this file seems to be processed after web.xml. – Alex Oct 03 '14 at 15:36
  • Unfortunatelly I'm behind a corporate firewall. I'm not able to chat. – Alex Oct 03 '14 at 17:06
  • I've achieved the answer (through an "experimental research"): my /resources/spring/application-config.xml was not properly configured. Tag was not present in this file. Other beans was normally working probably due to their scope to be dispatcher-servlet. Thanks for your help! – Alex Oct 03 '14 at 18:47
1

I was getting null pointer while accessing service class bean in filter class using Autowiring . I searched more than 100 links but not able to find solution. I am using spring Boot Application and configuration which is required to get bean in filter class :

FilterConfig.java which provides application context Object.

@Component
public class FilterConfig  implements ApplicationContextAware{

private static ApplicationContext context;


public static ApplicationContext getApplicationContext() {
       return context;
    }
public  static <T> T getBean(String name,Class<T> aClass){
    return context.getBean(name,aClass);
}

@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
    context = ctx;
}   

 }

in Filter class , I used this like :

 UserService userService =FilterConfig.getBean("UserService", UserService.class);

UserService this is bean name which is mentioned in

  @Service("UserService")
  public class UserServiceImpl implements UserService { ...}

No Configuration in main class of spring Boot :SpringBootServletInitializer

abhishek ringsia
  • 1,970
  • 2
  • 20
  • 28