1

Autant que je sache, CDI devrait fonctionner dans les filtres, mais je ne peux pas le faire fonctionner pour moi. Code se présente comme suit:@Inject dans le filtre ne fonctionne pas

@WebFilter(filterName="authFilter",servletNames={"Faces Servlet"}) 
public class AuthFilter implements Filter { 

    @Inject UserBean userBean; 

    public AuthFilter() { 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException { 
     userBean.doSomething(); // Causes NullPointerException 
     chain.doFilter(request, response); 
    } 
} 

UserBean.class

@Stateless 
public class UserBean extends JPABean{ 
// Omitted 
} 

CDI est activée, et l'injection fonctionne si je le fais manuellement via InitialContext.doLookup() ou dans un Servlet, comme ceci:

@WebServlet(name = "MyServlet", urlPatterns = {"/MyPage"}) 
@ServletSecurity(@HttpConstraint(rolesAllowed={"somerole"})) 
public class MyServlet extends HttpServlet { 

    @Inject private UserBean userBean; 

    @Override 
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     userBean.doStuff(); // Works 
     response.sendRedirect(request.getContextPath()); 
} 

Le CDI ne fonctionne-t-il pas dans les filtres? Dans ce cas, pourquoi pas? Si cela devait arriver, que pourrais-je faire de mal?

+0

Quel conteneur? JBoss AS 6 a un bug très simliar. Cela fonctionne-t-il si vous utilisez juste '@ EJB'? – BalusC

+0

JBoss AS 6 en effet ... @EJB fonctionnerait probablement. Très agaçant, je viens de faire une injection manuelle via InitialContext à la fin, mais bon de savoir la raison. –

Répondre

3

Dans cet exemple, j'injecte un bean CODI @ViewAccessScoped (RegisterView) dans un filtre, définissez une propriété dans le bean et accédez à une vue qui utilise le bean. Lorsque la page se charge, le nom d'utilisateur est défini sur "fred". Cela fonctionne également avec @SessionScoped (mais pas @RequestScoped ou @ViewScoped). Je pense que l'injection dynamique est nécessaire pour la sécurité des threads car il n'y a qu'une seule instance du filtre dans le conteneur Web et donc toutes les variables d'instance. Le problème à résoudre est que Faces Servlet ne s'est pas exécuté lorsque le filtre s'exécute, donc il n'y a pas de FacesContext. Le travail intelligent fait par getFacesContext() que j'ai levé directement de ce blog à partir de 2004, je ne sais pas de qui il a été écrit et il n'y a pas eu de contenu ajouté depuis quelques années, mais si quelqu'un le sait, faites le moi savoir! Peut-être que c'était BalusC dans ses jours plus jeunes. Il utilise une classe interne statique pour accéder à la méthode protectedServlet # setCurrentInstance().

Cela ne fonctionne pas si vous utilisez response.sendRedirect().

package uk.co.myco.jsfbeans.helper; 

import java.io.IOException; 
import javax.enterprise.inject.Instance; 
import javax.faces.FactoryFinder; 
import javax.faces.component.UIViewRoot; 
import javax.faces.context.FacesContext; 
import javax.faces.context.FacesContextFactory; 
import javax.faces.lifecycle.Lifecycle; 
import javax.faces.lifecycle.LifecycleFactory; 
import javax.inject.Inject; 
import javax.servlet.DispatcherType; 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletContext; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
import javax.servlet.annotation.WebFilter; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import uk.co.sportquest.entities.User; 
import uk.co.sportquest.general.BaseClass; 
import uk.co.sportquest.general.Log; 
import uk.co.sportquest.jsfbeans.RegisterView; 

/* 
* @author Brendan Healey 
* 
* http://www.thoughtsabout.net/blog/archives/000033.html 
* 
*/ 

@WebFilter(filterName = "SocialAuthFilter", urlPatterns = {"/pages/socialAuthFilter.xhtml"}, 
dispatcherTypes = {DispatcherType.FORWARD, DispatcherType.ERROR, DispatcherType.REQUEST, DispatcherType.INCLUDE}) 
public class SocialAuthFilter extends BaseClass implements Filter { 

    @Inject 
    private Instance<RegisterView> rvDynamic; 

    private ServletContext servletContext; 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 
     servletContext = filterConfig.getServletContext(); 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

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

     Log.log("testFilter: " + request.getPathInfo()); 

     FacesContext ctx = getFacesContext(req, res); 

     RegisterView registerView; 
     registerView = rvDynamic.get(); 

     User user = new User(); 
     user.setUserName("fred"); 
     registerView.setInputUser(user); 

     FacesContext.getCurrentInstance().getExternalContext().redirect("/pages/register.xhtml"); 

    } 

    @Override 
    public void destroy() { 
    } 

    private abstract static class InnerFacesContext extends FacesContext { 

     protected static void setFacesContextAsCurrentInstance(FacesContext facesContext) { 
      FacesContext.setCurrentInstance(facesContext); 
     } 
    } 

    private FacesContext getFacesContext(ServletRequest request, ServletResponse response) { 
     // Try to get it first 
     FacesContext facesContext = FacesContext.getCurrentInstance(); 
     if (facesContext != null) { 
      return facesContext; 
     } 

     FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY); 
     LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY); 
     Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE); 

     // Either set a private member servletContext = filterConfig.getServletContext(); 
     // in you filter init() method or set it here like this: 
     // ServletContext servletContext = ((HttpServletRequest)request).getSession().getServletContext(); 
     // Note that the above line would fail if you are using any other protocol than http 

     // Doesn't set this instance as the current instance of FacesContext.getCurrentInstance 
     facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle); 

     // Set using our inner class 
     InnerFacesContext.setFacesContextAsCurrentInstance(facesContext); 

     // set a new viewRoot, otherwise context.getViewRoot returns null 
     UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, ""); 
     facesContext.setViewRoot(view); 

     return facesContext; 
    } 

} 
Questions connexes