Setting ManagedBean values in another ManagedBean's method - jsf-2

If I am navigating from page one to page two, When I click on Page one's submit button, control goes to the managed bean written corresponding to page one, I want to fetch some result from database and show them to page two, If I set the Database values into the Managed bean corresponding to page two in the first Managed Bean's action method, then will I be able to get those on page two.
Please suggest if my approach is right?

You can inject let's say bean named Bean1 into Bean2 this way
#ManagedBean
#RequestScoped
public Bean2 {
#ManagedProperty(value="#{bean1}")//this is EL name of your bean
private Bean1 injectedBean;
public void setBean1(Bean1 value) {
injectedBean = value; //provide setter for it
}
#PostConstruct
private void init() {
List<YourData> list = injectedBean.getDBData(); //now you can fetch your list
}
Note that you have to provide setter for injection and scope of the injected bean should be always same or higher then the your beans scope (in this case Bean1 has to be at least RequestScope)
P.S. Also you could have some kind of DAO bean which could do all the database database operations for you (it can be EJB bean or even JSF Managed Bean) and then inject it to every ManagedBean which will require cooperation with your DB.

Related

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}

FacesContext.getCurrentInstance().getExternalContext().invalidateSession() calls posconstruct twice

I have managed bean by name studentManagedBean. In that bean I have used post construct to intialize studentsList. In another managed bean testbean I was using
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
and redirecting to page students.xhtml where I used to display students.
My question is when I used the FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); and redirected to student.xtml page, init method(post construct) used to call two times. When I commented the above line, init method(post construct) now calls only one time.
can any one tell me what is this invalidate session will exactly do.
#ManagedBean(name = "studentManagedBean" )
#SessionScoped
public class StudentManagedBean implements Serializable {
private List<SBean> stud;
#PostConstruct
private void init(){
this.stud=dao.getAllStudInfo();
}
#ManagedBean(name = "testBean" )
#SessionScoped
public class TestBean implements Serializable {
public String navigate(String name){
if(name.equals("Add student")){
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
return "student";
}
Apparently, the session scoped bean StudentManagedBean is also referenced in the current view. When the view get built/restored, it may create the bean if it's referenced during view build time. But if you're invalidating the session thereafter, the session scoped bean get destroyed (obviously, since it's stored in the session scope) and will be re-created again when the target view still references it during rendering of the view.
This must make completely sense. If you don't want that the bean is created before you invalidate the session, simply don't reference it anywhere in the current view, either directly in the view, or indirectly as a managed property or a programmatic EL evaluation of another bean which is directly referenced in the current view.
If you can't immediately figure out where it's been referenced, just put a debug breakpoint in the bean's constructor and explore the call stack for the who/what/why.

How to prevent #PostConstruct from being called on postback

When the page loads for the first time, the #PostConstruct is called, but when I perform a postback on this page, the #PostConstruct is called again.
How can I make it to run only on the initial request and not on every postback?
#PostContruct
public void init() {
// charge combos....
}
public void submit() {
// action
}
Apparently your bean is request scoped and thus reconstructed on every HTTP request. I'm not exactly sure why you'd like to prevent the #PostConstruct from being called again, as you would otherwise end up with an "empty" bean state which might possibly lead to form submit errors, but okay, you could add a check if the current request is not a postback.
public void init() {
if (!FacesContext.getCurrentInstance().isPostback()) {
// charge combos....
}
}
This way the "charge combos" part won't be invoked on postbacks.
Or, maybe your actual question is not "How to prevent postconstruct from being called on postback?", but more "How to retain the same bean instance on postback?". In that case, you'd need to put the bean in the view scope instead of in the request scope.
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
// ...
}
As long as you return null from action methods, this way the same bean instance will live as long as you're interacting with the same view by postbacks. This way the #PostConstruct won't be invoked (simply because the bean isn't been reconstructed).
See also:
How to choose the right bean scope?
use this import:
import javax.faces.view.ViewScoped; for #ViewScoped

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.

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