1 Reply Latest reply on Feb 4, 2011 8:27 AM by alesj

    How do I @Inject a CDI managed bean in a non-CDI bean? (Ex- Servlet Filter)

    infinity2heaven

      I have a simple security model for my app where I setup an Authenticator, Authorizer, and ServletFilter that uses the former two to check every url accessed. The Authenticator service is working as I can login/logout the form. The authorizer should work as well. The Servlet Filter does its job. However, I don't get a freshly initialized object at @Inject Authorizer below so end up in a NPE after successful login. Here is tje flow


      -- user accesses login page
      -- Authenticator.login is invoked, redirects to home (from faces-config.xml navigation)
      -- Servlet filter gets called and verifies that user is indeed logged in (isLoggedIn()) and proceeds to call authorize but fails since Authorizer is not injected.


      Interestingly, Authenticator should be null too but since login page was first accessed the component is initialized (context) and injected to the ServletFilter correctly.


      My question is -- How do I inject a CDI Managed bean (session/application/singleton, etc) to a non CDI managed bean if I don't know the context or Qualifier? I'm thinking of adding a cheap hack in Authenticator where it initalizes the authorizer but that doesn't seem right. Or maybe add a @Producer in Authenticator which returns an Authorizer ... what is the right way anyways?



      @ApplicationScoped
      @Named
      public class Authorizer {
      
         public boolean authorize() {
         ...
         }
      
      }






      @SessionScoped @Named
      public class Authenticator
           implements Serializable {
      
           public void login() {
            ...
           }
      
      }








      @WebFilter( filterName = "SecurityFilter", dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD }, urlPatterns = "/pages/secure/*" )
      public class SecurityFilter
           implements Filter {
      
           @Inject
           private Authenticator authenticator;
      
           @Inject
           private Authorizer authorizer;
      
                   ...
      
           @Override
           public void doFilter(
                ServletRequest request,
                ServletResponse response,
                FilterChain chain )
                throws IOException, ServletException {
       
                String viewId = httpRequest.getServletPath();
      
                if ( !authenticator.isAuthenticationRequired( viewId ) ) {
                     chain.doFilter( request, response );
                     return;
                }
      
                if ( !authenticator.isLoggedIn() ) {
                     httpResponse.sendRedirect( contextPath + LOGIN_PAGE);
                     return;
                }
      
                if ( !authorizer.authorize( viewId ) ) {
                     httpResponse.sendRedirect( contextPath + ACCESS_DENIED_PAGE );
                     return;
                }   
                
                chain.doFilter( request, response );        
            }
      
      }




      I also tried using @Singleton, @Session for Authenticator but no resolution. I don't think I can add @New for Authorizer in the filter since I believe it's only for CDI managed beans