Since JSF 2.0 it is preferred to use CDI beans over JSF managed beans [1]. Different annotations are available to support different scopes, e.g. @RequestScope or @SessionScope. Sometimes you need to access such a bean from a piece of software where you don’t have direct access to the FacesContext.

Lets assume, you run a different, non-JSF servlet and you need to access an instance of MyBean which is a JSF CDI bean.

public class MyServlet extends HttpServlet {

  @Override
  protected void doPost(HttpServletRequest request, 
                        HttpServletResponse response) {
    HttpSession session = request.getSession();
    MyBean myBean = ???
  }

}

The HttpSession object contains a map of all session objects. This includes instances of the CDI @SessionScoped objects. Accessing such an object is pretty easy. Bauke Sholz described this in [2].

MyBean myBean = (MyBean) session.getAttribute("myBean");

But, if we need to access a CDI @ViewScoped bean?

Within the session map, an entry “com.sun.faces.application.view.activeViewMaps” exists containing a map of maps of beans. We can iterate through it to extract the wanted bean.

    Map map = (Map) session.getAttribute(
               "com.sun.faces.application.view.activeViewMaps");
    MyBean myBean = null;
    for (Object entry : map.values()) {
      if (entry instanceof Map) {
        Map viewScopes = (Map) entry;
        if (viewScopes.containsKey(name)) {
          myBean = (MyBean) viewScopes.get(name);
          break;
        }
      }
    }

Using generics, we may create a small method to retrieve any @ViewScoped bean.

    ...
    MyBean myBean = retrieveBean(MyBean.class, session);
    ...
  }  


  private <T> T retrieveBean (Class<T> clazz, HttpSession session) {
    String name = clazz.getSimpleName().substring(0, 1).toLowerCase() 
                + clazz.getSimpleName().substring(1);
    Map map = (Map) session.getAttribute(
            "com.sun.faces.application.view.activeViewMaps");
    for (Object entry : map.values()) {
      if (entry instanceof Map) {
        Map viewScopes = (Map) entry;
        if (viewScopes.containsKey(name)) {
          return (T) viewScopes.get(name);
        }
      }
    }
    return null;
  }

Enjoy!

 

[1] Read about this in Web Development with Java and JSF

[2] stackoverflow.com/questions/2633112/get-jsf-managed-bean-by-name-in-any-servlet-related-class