How can I retrieve an object on #WindowScoped? - jsf-2

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

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

JSF 2 ManagedProperty is null

I know there are loads of questions on SO regarding this exact issue, but I couldn't find a solution to my problem. I'm trying to use a #ManagedProperty in JSF 2. I used the example from this page, but mine's not working:
#ManagedProperty("#{userSession}")
private UserSession userSession;
public void setUserSession(UserSession userSession) {
this.userSession = userSession;
}
Both the parent bean and the bean injected are session scoped. Both beans have the #ManagedBean attribute. No faces-config.xml declarations, no EJBs, no use of Spring. One thing I noticed from that example is that both the bean classes implement Serializable. Mine do not, and I'm not sure if that is making the difference.
When I use this code, I get a NullPointerException when I try to operate on userSession. However, I know a session exists, because when I use #BalusC's findBean convenience method, it works. One thing with this though, is that my code only works if I call userSession = findBean("userSession") inside the same method where I'm "doing stuff". If I initialize userSession in the bean's constructor, I get another NPE. Any ideas?

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}

Why does the #PostConstruct method not get called using BeanManager.getReference() to obtain an instance?

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

JSF 2.0 pass data between beans (or pages?)

I'm working with JSF 2.0
I have a form in my admin section where I am going to select some users in a list.
The form (selectusers.xhtml) is adding these users to a list in a bean (SelectUsers.java).
After I have selected some user(s), I will pass the list of the user(s) from SelectUsers.java to another bean (AddAddressBean.java) and continue add information in another form (addadress.xhtml) which set other properties related to AddAddressBean for each user.
I do not know how to implement it. I would like that AddAddressBean.java shall be independent (so I can use it together with other beans), so I prefer that AddAddressBean.java shall not know about other beans.
Can you please help me? =)
B.R Carl
Several quick things come to mind :
Perhaps you could have a single bean only for those related pages, using #SessionScoped or the shorter CDI's #ConversationScope, or and this is the best of the three, the DeltaSpike #ViewAccessScoped
When clicking the button on page 1 where it'll take you to page 2, in the 1st bean, you can make use of Flash object to store objects you want to pass, and in the second bean's #PostConstruct method, you could get all the objects from the Flash object
If you dont mind using session scope, you can still have 2 beans, and one bean can refer to another bean using the jsf way(#ManagedProperty), or the Java EE inject way(#Inject) or the spring way if you use spring (#Autowired)
This how i implemented (used ConversationScoped as #bertie said ).
bean 1:
#Named("conversationBean1")
#ConversationScoped
public class ConversationBean1 implements Serializable {
//---start conversation----
}
bean 2:
#Named("conversationBean2")
#ConversationScoped
public class ConversationBean2 implements Serializable
{
#Inject
private ConversationBean1 conversationBean1;
}

Resources