Howto access JSF2 #ViewScoped beans via ExternalContext? - jsf-2

In JSF1 you can access the bean instances of your current FacesContext by
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext()
ev.getApplicationMap().get(beanName) // get an #ApplicationScoped bean instance
ev.getSessionMap().get(beanName) // get a #SessionScoped bean instance
ev.getRequestMap().get(beanName) // get a #RequestScoped bean instance
In JSF2 #ViewScoped has been introduced, but I can't find a corresponding getViewMap() method on ExternalContext? I am using latest JSF 2.1.1-b04.
Am i misunderstanding some aspects of a #ViewScoped bean? Is there another good-practice to get a #ViewScoped bean instance on the server side?
Thanks,
Steve

Try to eval expression (evaluateExpressionGet):
context.getApplication().evaluateExpressionGet(context, "#{beanName}", BeanClass.class)

View scoped data is stored in the view root. You can get this from the context.

Related

Remove/destroy session scoped CDI managed bean [duplicate]

This question already has answers here:
Removing specific CDI managed beans from session
(2 answers)
Closed 1 year ago.
I have a session scoped CDI managed bean:
#Named
#SessionScoped
public class SampleBean implements Serializable {
// ...
}
I need to remove this bean from the session after a certain flow for which I used the following code like as seen in this answer:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.getSessionMap().remove("sampleBean");
However, it does not work and the SampleBean remains in the session.
Am I missing something?
In contrary to JSF managed beans, CDI managed beans are not stored directly by their managed bean name in the session map. They are instead stored in server's memory by the CDI manager implementation (Weld, OpenWebBeans, etc) using e.g. session ID as key.
The trick which you used there is therefore not applicable on CDI managed beans. You need to look for an alternate approach. The right approach in this particular case is to use #ConversationScoped instead of #SessionScoped. In properly designed web applications, there should never be the need to manually terminate a scope. So using #SessionScoped for a conversation/flow was already wrong in first place.
#Inject
BeanManager beanManager;
.....
AlterableContext ctxSession = (AlterableContext) beanManager.getContext(SessionScoped.class);
for (Bean<?> bean : beanManager.getBeans(YourSessionBeanToBeDestroyedClass.class)) {
Object instance = ctxSession.get(bean);
if (instance != null)
ctxSession.destroy(bean);
}
And this ¿?
FacesContext
.getCurrentInstance()
.getApplication()
.createValueBinding( "#{yourBeanName}").setValue(FacesContext.getCurrentInstance(), null );

EL session attribute and managed bean access

I am confused about expression language 2 bean-view communication syntax.First of all.Is it possible to have one more managed bean with same name but different scobes.if it is what about accessing them via expression language
on the other hand;
consider there is an attribute in session called DemoBean and there is a session Scobed managed bean called DemoBean as well,
if I try to access this bean via EL like this #{DemoBean} // refers bean or attribute?
they say #{sessionScobe} is the way to access session attributes but
just #{sessionattributename} is valid ? and when I put an object to the session map is it referanced or copied?
JSF's aim is to manage session attributes itself for you. That means you should forget about keeping/recovering session map attributes manually, because you'll be able to do it using JSF's mechanisms.
When you want to keep some info for the whole application, use #ApplicationScoped annotation into your managed bean. You can do the same for sessions, requests or concrete views, using #SessionScoped, #RequestScoped and #ViewScoped annotations.
So, if you want to store some attribute in session:
#ManagedBean
#SessionScoped
public class SessionScopedBean{
public String sessionAttribute;
//Getter and setter
}
You can recover/change the value of the attribute of the bean using the FacesContext:
FacesContext context = FacesContext.getCurrentInstance();
SessionScopedBean bean = (SessionScopedBean) context.getApplication()
.evaluateExpressionGet(context, "#{sessionScopedBean}", SessionScopedBean.class);
bean.setSessionAttribute("value");
Remember JSF beans are by default named with bean's name with the first character lowercased. And remember also this bean will be null at the first hit if you don't initialize yourself. You can do it in an easy way using a PreRenderViewEvent in the bean you want to initialize and executing it for example in your login page. That ensures the bean will keep alive for the rest of the session.
Finally, that's the way you'll access your session attribute from your view:
#{sessionScopedBean.sessionAttribute}

jsf 2 Session bean created for every request [duplicate]

This question already has an answer here:
#SessionScoped bean looses scope and gets recreated all the time, fields become null
(1 answer)
Closed 6 years ago.
ello
I have 2 Managed beans, one View scoped, the other Session scoped. The View scoped bean is defined as
#ManagedBean
#ViewScoped
public class InvoiceController implements Serializable {
private static final long serialVersionUID = 1L;
#ManagedProperty(value="#{invoiceService}")
private InvoiceService invoiceService;
The session scoped bean as
#ManagedBean
#SessionScoped
public class InvoiceService implements Serializable{
I am using the session scoped bean to hold a flag used to decide if a panel should be rendered, when I run this through the debug I find that every time I call the method on the sesison bean, it is a new instance of the bean and therefore does not retain the value of my flag between requests.
What am I doing wrong?
That can happen if you have imported #SessionScoped from the javax.enterprise.context package instead of from the javax.faces.bean package. The former works on CDI #Named beans only, while the latter works on JSF #ManagedBean beans only.
A JSF #ManagedBean without any valid scope would default to #NoneScoped which means that it's newly constructed on every single EL expression referencing the bean, such as the #ManagedProperty. This explains the symptoms you're seeing.
I had a similar problem. I use a save-method in the view scoped bean that calls a method in the session scoped bean to update some values.
This is what I found out by debugging (excuse my non-Java-guru English):
When first loading the page, the instance number of the injected session bean was for example 111111.
But in the save-method (and all other methods called by an action like a commandButton or action listeners btw), suddenly the session bean was of another instance (say 222222).
Both instances 111111 and 222222 contained the very same values.
All methods I called now were done in the 222222 instance and it changed values in there as I wanted it. But the 111111 instance remained untouched and unchanged.
So 222222 was basically a deep(?) clone of 111111, and not even a copy.
But, after the save-method was done and the page got reloaded, the original 111111 instance was used again in the view scope bean.
The 222222 instance just got thrown to the garbage.
My solution for this problem:
I'm not using the ManagedProperty injection anymore.
Instead I made some helper code to get the session bean wherever I need it (aka in the view scoped bean methods):
public Object getSessionBean(String sessionBeanName)
{
return FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(FacesContext.getCurrentInstance().getELContext(), null, sessionBeanName);
}
For your example above, the call would be:
InvoiceService invoiceService = (InvoiceService) helper.getSessionBean("invoiceService");
Call it in your methods, do not store it as a field in the view scoped bean.
I hope this somehow helps you fix your problem.

Use Bean inside Managed Bean

how can i use a bean inside other bean ?
I use this solution, what's the best way ?
#ManagedBean(name="firstBean")
public class FirstBean implements Serializable{
#ManagedProperty(value="#{myBean}")
private MyBean myBean;
...
//(get/set method)
}
I'm new in JSF and JSP so probably it's a bad practies.
Your solution is the right one to inject another bean.
You only need the setter for the injected bean.
Are you having any issues\errors with it?

How can I retrieve an object on #WindowScoped?

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);
// ...

Resources