Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a SessionScoped CDI bean from inside a Filter?

This question is related to a previous one on writing a session timeout handler.

The answer in that thread involved accessing various session-scoped managed beans from the servlet. The recommendation (as seen here) is to do this in the filter:

HttpSession session = request.getSession(false);
User user = (session != null) ? (User) session.getAttribute("user") : null;

Presumably this fetches a session bean of class User. The problem is this doesn't work.

What goes wrong are that the beans are there in the session attributes, but they are wrapped by Weld facilities. I wrote the doFilter() method as follows:

public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    String sp = req.getServletPath();
    System.out.println("------------------------");
    System.out.println("doFilter(): " + sp);

    if (!sp.startsWith("/javax")) {  // eliminates many requests
        HttpSession session = req.getSession();
        Enumeration<String> en = session.getAttributeNames();
        int count = 0;            
        while (en.hasMoreElements()) {
            String e = en.nextElement();
            System.out.println("Attribute " + ++count + ": " + e);
        }
    }
    chain.doFilter(request, response);
}

When this dumps out the session attributes, I typically get something like this:

INFO: ------------------------
INFO: doFilter(): /Display.xhtml
INFO: Attribute 1: org.jboss.weld.context.http.HttpSessionContext#org.jboss.weld.bean-WEB-INF/lib/myfaces-extcdi-bundle-jsf20-1.0.1-ManagedBean-class org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.EditableWindowContextManagerProxy
INFO: Attribute 2: org.jboss.weld.context.http.HttpSessionContext#org.jboss.weld.bean-MyApp5-ManagedBean-class com.app.Login
INFO: Attribute 3: org.jboss.weld.context.conversation.ConversationIdGenerator
INFO: Attribute 4: com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap
INFO: Attribute 5: org.jboss.weld.context.ConversationContext.conversations
INFO: Attribute 6: facelets.ui.DebugOutput
INFO: Attribute 7: javax.faces.request.charset
INFO: Attribute 8: org.apache.myfaces.extensions.cdi.core.api.scope.conversation.WindowContext:EXISTING_WINDOW_ID_LIST

Attribute #2 seems to represent the bean that I want. Needless to say a call to session.getAttribute("login") doesn't work.

Can anyone say how to access the underlying managed bean? I would prefer to do it in a way that was not tied to Weld, but that may not be possible.

like image 425
AlanObject Avatar asked Oct 19 '11 00:10

AlanObject


2 Answers

This approach works for session scoped JSF @ManagedBean only, not for CDI @Named bean.

You need to @Inject it as a property of the filter.

@Inject
private User user;
like image 139
BalusC Avatar answered Nov 16 '22 05:11

BalusC


import org.jboss.weld.context.SerializableContextualInstanceImpl;

    HttpSession httpSession = (HttpSession) facesContext.getExternalContext().getSession(false);
    Enumeration<String> attribs = httpSession.getAttributeNames();
    String attrib = null;
    while (attribs.hasMoreElements()) {         
        attrib = attribs.nextElement();
        Object obj = httpSession.getAttribute(attrib);
        if(obj instanceof SerializableContextualInstanceImpl){
            SerializableContextualInstanceImpl impl = (SerializableContextualInstanceImpl)obj;
            //here: MyObject myObj= (MyObject)impl.getInstance();
        }           
    }
like image 38
liukvar Avatar answered Nov 16 '22 04:11

liukvar