10

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.

Community
  • 1
  • 1
AlanObject
  • 9,613
  • 19
  • 86
  • 142

2 Answers2

18

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;
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 2
    BalusC do you ever sleep? I just tried annotating my filter with **`@Named`** and doing an **`@Inject`** of my **Login** bean. It worked! I had no idea that the CDI service would work in a **Filter**. I suppose this means that the **Filter** object is instantiated for each request cycle, not just once for the Servlet's lifetime. – AlanObject Oct 19 '11 at 01:01
  • 1
    It's only 21:02 right now :) It should just work if you annotate the filter with `@WebFilter`. I'd rather not make it `@Named` (similarly, `@Inject` should work in `@WebServlet` servlets as well). The CDI is more a proxy. The objects are injected on a threadlocal basis, the to-be-injected instance doesn't need to be of the same or a broader scope. – BalusC Oct 19 '11 at 01:02
  • 1
    @BalusC: Is this solution thread safe as `user` become a member var of the filter? – Toru May 03 '18 at 08:49
  • 1
    @Toru: only if you don't omit `@Inject`. – BalusC May 13 '18 at 08:40
  • @BalusC you are one of a kind – Jalal Sordo Feb 24 '22 at 01:40
5
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();
        }           
    }
liukvar
  • 106
  • 1