As far as I know, there are many ways to get attributes in other backing beans.
First is:
otherBean = (OtherBean) FacesContext.getCurrentInstance()
.getELContext()
.getELResolver()
.getValue(FacesContext
.getCurrentInstance()
.getELContext(), null, "OtherBean");
String str=otherBean.someString;
And the second is to use session map:
(Set parameters to session map in other Bean)
FacesContext.getCurrentInstance()
.getExternalContext()
.getSessionMap()
.put("someString",someString);
(And get the parameters in the current Bean)
String str= (String) FacesContext.getCurrentInstance()
.getExternalContext()
.getSessionMap()
.get("someString");
And the last is to use Annotation
#ManagedProperty("#{otherBean}")
private OtherBean otherBean;
String str=otherBean.someString;
So which one should I use? What's the differences between those methods? Or is the methods mentioned above wired?
I would use always the last one because it is simply the most convenient. I would use FacesContext only if you can't inject the property or the bean using annotations. FacesContext is a singleton. Unit testing code using FacesContext is a pain.
I've never seen the first method (using the EL resolver) been used outside framework code.
Related
When I access simple model data like the username using : ${username} everything seems to be fine. But when I try to use ${userdata.uname} I get an error like :
Could not find property uname in class com.mydom.datahandling.userdata
userdata is java class I add to the ModelAndView
ModelAndView mav = new ModelAndView("page37");
mav.addObject("sessionID",ID);
mav.addObject("userdata",p37userdata);
What do I need to do differently ? This seems to be happening whenever I try to use something other than a primitive type or String. I obviously need a bit more education. Do I need to serialize p37userdata?
userdata is
public class userdata{
public String uname;
public String otherstuff;
}
The objects you reference from your EL in your JSP should be java beans (or a map). According to wikipedia (the source of all truth) A bean has the following properties:
They are serializable, have a 0-argument constructor, and allow access
to properties using getter and setter methods.
So you should probably add getters and setters to your userdata class.
I've tried every solution from a couple dozen google searches: getRequestMap, ElResolver, evaluateExpressionGet and so on. Nothing, absolutely nothing, works. I get null every time. Here is the relevant code:
#ManagedBean(name="readerBean")
#ViewScoped
public class ReaderBean implements Serializable {...
And in the PhaseListener:
public void beforePhase(PhaseEvent event) {
if (event.getPhaseId() == PhaseId.RESTORE_VIEW) {
ReaderBean r = null; //The Managed Bean
try {
FacesContext fctx = FacesContext.getCurrentInstance();
r=(ReaderBean) fctx.getExternalContext().getRequestMap().get("readerBean");
r=(ReaderBean) fctx.getELContext().getELResolver().getValue(fctx.getELContext(), null, "readerBean");
r=(ReaderBean) fctx.getApplication().getExpressionFactory().createValueExpression(fctx.getELContext(), "#{readerBean}", ReaderBean.class).getValue(fctx.getELContext());
r=(ReaderBean) fctx.getApplication().evaluateExpressionGet(fctx, "#{readerBean}", ReaderBean.class);
Nothing works!!!
As to the request map approach, it fails because a view scoped bean is not stored in the request scope. It's instead stored in the view scope. As to the other approaches, they fail because the view scoped bean is stored in the view and thus only available after the view has been restored. However, you're trying to get it before the view has been restored. This is a chicken-egg problem.
You need to revise your approach. Perhaps the bean needs to be a request scoped one? Perhaps the logic needs to be executed at a different phase? Perhaps the logic needs to be performed in the bean itself instead? Etc.
As the concrete functional requirement for which you thought that this is the right solution is unmentioned in the question, I can't point you in the right direction.
We are currently moving from JSF-ManagedBeans to CDI. Unfortunately we have made excessive use of the EL-Resolver in the past in order to gain static access to session scoped beans managed by JSF.
Since CDI dependency injection is not available everywhere I rewrote the existing static lookup to make use of the BeanManager (Using SEAM-Solder extending BeanManagerAware).
Iterator<Bean<?>> iterator = beans.iterator();
Bean<T> bean = (Bean<T>) iterator.next(); // possible NPE, I know :)
CreationalContext<T> creationalContext = beanManager.createCreationalContext(bean);
T contextual = (T) beanManager.getReference(bean, type, creationalContext);
return contextual;
The code works and returns a container managed instance of the desired bean. BUT: the methods annotated with #PostConstruct do not get called using getReference(). Perhaps you guys know how to do it. Couldn't find anything googling the issue :-/
Best regards!
You should be using Application#evaluateExpressionGet() for this. Not only for CDI beans, but actually also for JSF beans you previously had.
FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);
// ...
Much cleaner, however, is to just use CDI's #Inject or JSF's #ManagedProperty instead.
See also:
Get JSF managed bean by name in any Servlet related class
In this post Dynamic ui:include I asked how I could store an object in some state that could permit me to load a new windows, or tab, of the same browser and it was not stored also in the new windows. Adrian Mitev told me to use #WindowScoped, an option of MyFaces extension called CODI and i tried to implement it.
Now I should say that I'm blind and when I tried to open Apache Wiki my browser crashes on many pages so I can't read the guides.
However I add the source code on my project and the compiler didn't give any errors.
The problem is that now thepage when I try to retrive the bean that I stored by #WindowScoped doesn't work properly!
I use this code in my bean:
#ManagedBean (name="logicBean" )
#WindowScoped
In include.xhtml I retrieve the parameter with this code:
<ui:include src="#{logicBean.pageIncluded}"/>
And in my other beans I retrieve the LogicBean with this code (and I'm sure that the problem is on this code)
LogicBean l = (LogicBean) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("logicBean");
How can I retrive the "correct" LogicBean object?
You're trying to get the LoginBean from the session map. This works only for session scoped beans with the standard JSF #SessionScoped annotation.
The canonical way to access other beans is using #ManagedProperty on the retrieving bean.
E.g.
#ManagedBean
#RequestScoped
public class OtherBean {
#ManagedProperty("#{logicBean}")
private LogicBean logicBean;
// Getter+Setter.
}
If you really need to access it inside the method block by evaluating the EL programmatically, you should be using Application#evaluateExpressionGet() instead:
FacesContext context = FacesContext.getCurrentInstance();
LogicBean logicBean = context.getApplication().evaluateExpressionGet(context, "#{logicBean}", LogicBean.class);
// ...
My requirement is " Our users are Authenticated by External System using SSO".
On successful authentication the external system returns header variables viz. userId,
firstName, lastName etc to our System.
Currently I am able to retrieve these header variables using
request.getHeader("userId") in my JSP page.
But I am using JSF 2.0 and not able to figure out as to how this can be done in JSF. I saw one example here on Stack overflow ...
Map<String, String> requestHeaders = context.getExternalContext().getRequestHeaderMap();
String userName = requestHeaders.get(requestHeaderName);
but there was no further response as how this will be invoked on the backing bean.
Any pointer or sample code would be helpful.
The context is here just the current instance of the FacesContext. This is a request based threadlocal variable which is always available throughout all the JSF code which is controlled by the FacesServlet.
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> requestHeaders = context.getExternalContext().getRequestHeaderMap();
String userName = requestHeaders.get(requestHeaderName);
// ...
You can invoke this in for example the bean's constructor, the bean's #PostConstruct method, the bean's action(listener) method, etcetera. The right place depends on the moment you want to collect this information and what you want to do with this information.