Get JSF managed bean by name in any Servlet related class
Solution 1
In a servlet based artifact, such as @WebServlet
, @WebFilter
and @WebListener
, you can grab a "plain vanilla" JSF @ManagedBean @RequestScoped
by:
Bean bean = (Bean) request.getAttribute("beanName");
and @ManagedBean @SessionScoped
by:
Bean bean = (Bean) request.getSession().getAttribute("beanName");
and @ManagedBean @ApplicationScoped
by:
Bean bean = (Bean) getServletContext().getAttribute("beanName");
Note that this prerequires that the bean is already autocreated by JSF beforehand. Else these will return null
. You'd then need to manually create the bean and use setAttribute("beanName", bean)
.
If you're able to use CDI @Named
instead of the since JSF 2.3 deprecated @ManagedBean
, then it's even more easy, particularly because you don't anymore need to manually create the beans:
@Inject
private Bean bean;
Note that this won't work when you're using @Named @ViewScoped
because the bean can only be identified by JSF view state and that's only available when the FacesServlet
has been invoked. So in a filter which runs before that, accessing an @Inject
ed @ViewScoped
will always throw ContextNotActiveException
.
Only when you're inside @ManagedBean
, then you can use @ManagedProperty
:
@ManagedProperty("#{bean}")
private Bean bean;
Note that this doesn't work inside a @Named
or @WebServlet
or any other artifact. It really works inside @ManagedBean
only.
If you're not inside a @ManagedBean
, but the FacesContext
is readily available (i.e. FacesContext#getCurrentInstance()
doesn't return null
), you can also use Application#evaluateExpressionGet()
:
FacesContext context = FacesContext.getCurrentInstance();
Bean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);
which can be convenienced as follows:
@SuppressWarnings("unchecked")
public static <T> T findBean(String beanName) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
}
and can be used as follows:
Bean bean = findBean("bean");
See also:
Solution 2
I use the following method:
public static <T> T getBean(final String beanName, final Class<T> clazz) {
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
return (T) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, beanName);
}
This allows me to get the returned object in a typed manner.
Solution 3
Have you tried an approach like on this link? I'm not sure if createValueBinding()
is still available but code like this should be accessible from a plain old Servlet. This does require to bean to already exist.
http://www.coderanch.com/t/211706/JSF/java/access-managed-bean-JSF-from
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
// May be deprecated
ValueBinding binding = app.createValueBinding("#{" + expr + "}");
Object value = binding.getValue(context);
Solution 4
You can get the managed bean by passing the name:
public static Object getBean(String beanName){
Object bean = null;
FacesContext fc = FacesContext.getCurrentInstance();
if(fc!=null){
ELContext elContext = fc.getELContext();
bean = elContext.getELResolver().getValue(elContext, null, beanName);
}
return bean;
}
Related videos on Youtube
Konrad Garus
Quality nut. So disappointed with "good enough" and "I don't care I'm too busy chasing my tail".
Updated on July 08, 2022Comments
-
Konrad Garus almost 2 years
I'm trying to write a custom servlet (for AJAX/JSON) in which I would like to reference my
@ManagedBeans
by name. I'm hoping to map:http://host/app/myBean/myProperty
to:
@ManagedBean(name="myBean") public class MyBean { public String getMyProperty(); }
Is it possible to load a bean by name from a regular servlet? Is there a JSF servlet or helper I could use for it?
I seem to be spoilt by Spring in which all this is too obvious.
-
McDowell about 14 yearsI'm not sure if you can use these new annotations outside JSF/EL, but I'd start by looking at the JSR 299 spec: jcp.org/en/jsr/detail?id=299
-
Konrad Garus about 14 yearsOther people having problems with similar issues can also check bpcatalog.dev.java.net/ajax/jsf-ajax (related to AJAX and request mapping/handling, not getting beans by name)
-
-
McDowell about 14 yearsThis probably won't work in a regular servlet. The FacesContext is a per-request thread-local artefact set up by the JSF lifecycle (usually the FacesServlet).
-
BalusC about 14 yearsValueBinding is deprecated since JSF 1.2 over 4 years ago.
-
James P. about 14 years@BalusC: It shows how up to date I am lol. On a sidenote, using a search engine to research techniques is turning out to be counterproductive with all the old information out there. @McDowell: That actually makes sense. I'll do a test just to see what happens.
-
jnt30 over 12 yearsYou're second suggestion about just injecting the bean was so amazingly simple I had totally overlooked it. As always, your response is perfectly to the point. Thanks so much for your work here on SO.
-
BalusC over 11 yearsThis is already covered by the currently accepted answer and even in a more convenient way (
Class
argument is namely unnecessary in this construct). -
Marc Juchli over 9 yearsIn the meantime (speaking as of JSF 2.2) it seems like the method evaluateExpressionGet was extended with a third parameter that allows to specify the expected class so casting won't be necessary anymore.
PostBean bean = context.getApplication().evaluateExpressionGet(context, "#{beanName}", PostBean.class);
-
BalusC over 9 years@Marc: Has been in from the beginning. Was just a leftover from a copypaste mistake I guess. Answer has been corrected. Thank you for notifying.
-
Tiny almost 9 years
FacesContext
is available even though thestatic
utility methodfindBean()
is defined inside a plain Java class. How is it available there in a plain Java class which is not managed by JSF? -
BalusC almost 9 years@Tiny: it's in turn called by a JSF artifact within the same thread.
-
Fernando Pie almost 8 yearsHi I get FacesContext context = FacesContext.getCurrentInstance(); context=null why?? and Trying to use HttpServletRequest request like this Bean bean = (Bean) request.getSession().getAttribute("ingresoSistema"); I got this: Servlet.service() for servlet servletsimple threw exception java.lang.IllegalStateException: Cannot create a session after the response has been committed. My bean: @ManagedBean(name = "ingresoSistema") @SessionScoped
-
Fernando Pie almost 8 yearsWhat kind of servlet do you use? mate
-
Fernando Pie almost 8 yearsI try to to this from a servlet but it doesn`t work.
-
Anil almost 8 yearsIt is HttpServlet.
-
Jasper de Vries about 7 years@BalusC I was expecting
findBean(String beanName)
to be available in showcase.omnifaces.org/utils/Beans, but it's not. Is there any reason for that (other than keeping it strictly CDI)? -
BalusC about 7 years@Jasper: You can use
Faces#evaluateExpressionGet()
for this. -
Jasper de Vries almost 7 years@BalusC OK, but you would still have to use
"#{" + beanName + "}"
, right? Or am I being lazy here? ;-)