views:

1077

answers:

2

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.

A: 

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);
James P.
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).
McDowell
ValueBinding is deprecated since JSF 1.2 over 4 years ago.
BalusC
@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.
James P.
+4  A: 

In a Servlet, you can get request scoped beans by:

Bean bean = (Bean) request.getAttribute("beanName");

and session scoped beans by:

Bean bean = (Bean) request.getSession().getAttribute("beanName);

and application scoped beans by:

Bean bean = (Bean) getServletContext().getAttribute("beanName");

Regardless of the scope, when you're inside the FacesContext, the normal JSF2 way is using Application#evaluateExpressionGet():

FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);

which can be convenienced as follows:

public static <T> T findBean(String beanName, Class<T> beanClass) {
    FacesContext context = FacesContext.getCurrentInstance();
    return beanClass.cast(context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", beanClass);
}

and can be used as follows:

Bean bean = findBean("bean", Bean.class);

If you're running in a dependency injection capable framework/container, it's even more easy:

@Inject
private Bean bean;
BalusC
Thank you, it explains even more than I hoped for.
Konrad Garus
You're welcome.
BalusC