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