Get JSF managed bean by name in any Servlet related class

154,957

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 @Injected @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;
}
Share:
154,957

Related videos on Youtube

Konrad Garus
Author by

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, 2022

Comments

  • Konrad Garus
    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
      McDowell about 14 years
      I'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
      Konrad Garus about 14 years
      Other 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
    McDowell about 14 years
    This 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
    BalusC about 14 years
    ValueBinding is deprecated since JSF 1.2 over 4 years ago.
  • James P.
    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
    jnt30 over 12 years
    You'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
    BalusC over 11 years
    This 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
    Marc Juchli over 9 years
    In 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
    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
    Tiny almost 9 years
    FacesContext is available even though the static utility method findBean() is defined inside a plain Java class. How is it available there in a plain Java class which is not managed by JSF?
  • BalusC
    BalusC almost 9 years
    @Tiny: it's in turn called by a JSF artifact within the same thread.
  • Fernando Pie
    Fernando Pie almost 8 years
    Hi 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
    Fernando Pie almost 8 years
    What kind of servlet do you use? mate
  • Fernando Pie
    Fernando Pie almost 8 years
    I try to to this from a servlet but it doesn`t work.
  • Anil
    Anil almost 8 years
    It is HttpServlet.
  • Jasper de Vries
    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
    BalusC about 7 years
    @Jasper: You can use Faces#evaluateExpressionGet() for this.
  • Jasper de Vries
    Jasper de Vries almost 7 years
    @BalusC OK, but you would still have to use "#{" + beanName + "}", right? Or am I being lazy here? ;-)