File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes JSF and the fly likes Passing data between beans Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "Passing data between beans" Watch "Passing data between beans" New topic
Author

Passing data between beans

Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
This is I'm sure a very common problem, and probably quite simple if you know what to do, and I've looked around online, including this newsgroup, but can't find a specific answer that can help, but I want to be able to pass information between two beans.

I have two or more classes with quite a lot of code, but let's suppose we have just the two following very simple classes:



In the faces-config.xml file I would have something like this if I use dependency injection:



Then on my web pages I might have code such as:


Etc. In the link
http://wiki.apache.org/myfaces/AccessingOneManagedBeanFromAnother
they mention dependency injection, but it isn't very clearly explained, and I would appreciate help with a specific example that explains how I can pass information from one bean to another in the Java code, and how this is referenced from a page.

Alternatively, lookup is given on that link, but again it's not very clear how this is done. I'm using MyFaces 1.2, so would most appreciate how to pass information between beans, and which method is best to use. A simple example would help me a lot, many thanks.

Christopher Sharp
Venkat Sadasivam
Ranch Hand

Joined: May 10, 2008
Posts: 139
<property-name>beanb</property-name>
<value>#{beanb}</value>

When you use above XML tags, JSF container will automatically inject the specified managed bean. For the above example you must have getter and setter method for beanb in MyBeana class.


“Any fool can write code that a computer can understand. Good programmers write code that humans can understand. ”<br>
-Martin Fowler
Jerwin Louise Uy
Ranch Hand

Joined: Oct 27, 2007
Posts: 75
FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext el = facesContext.getELContext();
Application app = facesContext.getApplication();
ExpressionFactory ef = app.getExpressionFactory();
ValueExpression ve = ef.createValueExpression(el, expression, type);
ve.setValue(el, value);

where expression is the EL expression in string format and type is the Class, value is any Object passing the IS-A test.

For your example, before invoking the application phase and translating the logical outcome of the next page, you can have something like this.


public String nextPage() {

FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext el = facesContext.getELContext();
Application app = facesContext.getApplication();
ExpressionFactory ef = app.getExpressionFactory();
ValueExpression ve = ef.createValueExpression(el, "#{beanb}", MyBeanb.class);
MyBeanb b = new MyBeanb();
// alter the state of b here
ve.setValue(el, b);

return "nextPage"

}

Whenever JSF encounters an EL, it first looks in the scope defined in the faces-config.xml. If it does not find any instance of the managed bean mapped to the expression "#{beanb}", it invokes the constructor and set it in the scope. That is what we get when our direct to a page and it does not encounter any instance. What we are doing here is creating the instance ourselves and setting it in the context. Of course, the same thing is achieved if we used this line of code -

MyBeanb b = new MyBeanb();
// alter the state of b here
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext ec = facesContext.getExternalContext();
ec.getRequestMap().put("beanb", b);

The second approach considers that scope of the managed bean. Using the first approach, the ValueExpression is automatically mapped to the defined scope in the faces-config.xml

I hope this helps.

Regards.
[ August 06, 2008: Message edited by: Jerwin Louise Uy ]

Uy Jerwin Louise Vergara
Junior Developer / Research and Development at Incuventure Partners Corporation
email: jerwin.uy@incuventure.net
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
OK, many thanks for the two replies so far. I've tried the first, but I can't get it to work. Here is my specific code:



Where I have initialized userlist to a string for the purposes of the test.
In the real code it is picked up from a file.

In my second class I want to get the value of userlist from the class above:



And in my faces-config.xml I have the following code:



However, in attempting to navigate to a page where the LoginBean tries to get the value of userlist, I get the error message:
java.lang.NoSuchMethodException: Unknown property 'FormBean'.

Could someone kindly advise me what is going wrong here. In the mean time I will look at the second method, which will require some extra code.

Many thanks - Christopher Sharp
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
Well, I was unable to get the first method to work using the faces-config.xml file, but at least I've got the second method to work in part.

The class FormBean from above is unchanged, but in my LoginBean from above I now have the getter for the userlist with the code you provided, together with the loggedin in boolean as follows:



and in the faces-config.xml file I've removed the bean dependencies, so I now just have:



Basically what I want to do is also be able to test whether the user has logged in successfully from within the FormBean class. Would I do something like:



in the getUserlist method above, and create a setLoggedin() method in the FormBean class? If this works, perhaps it would be better to put the code you provided in the constructor of LoginBean so that this can be done anywhere from within LoginBean. The status of loggedin has to be kept for the full session.

I would appreciate some help with this. It's getting a bit late here, as I'm in Lyon, France, so I'm 9 hours ahead of Tucson, Arizona, where I am normally based. I'm in the astronomy department, and nobody here know any Java, much less JSF, and most people are away on vacation anyway.

Christopher Sharp
Jerwin Louise Uy
Ranch Hand

Joined: Oct 27, 2007
Posts: 75
The drawback in putting the code in the constructor of the LoginBean is that after the Managed Bean Creation Facility of JSF invokes an instance of LoginBean whether or not the user has successfully logged in or not, there is no way of changing the internal state of LoginBean aside from
getting the associated instance in the session and altering or creating a new instance of LoginBean and setting it again in the session scope.

You can use this code to get a specific instance of a managed bean given that they do exist in the scope,

FacesContext facesContext = FacesContext.getCurrentInstance();
ELContext el = facesContext.getELContext();
Application app = facesContext.getApplication();
ExpressionFactory ef = app.getExpressionFactory();
ValueExpression ve = ef.createValueExpression(el, expression, type);
return ve.getValue(el);

where expression is the string representation of el, i.e. "#{beanKey}
type is the Class, ve.getValue will return an Object.

Regards.
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
OK, many thanks, that looks very helpful indeed. So basically I can have something like this in my LoginBean class:



Then elsewhere in the code I can access the methods in the object.

I'm still new to JSF and have not had enough experience yet with Java, so sometimes I get confused about accessing instances.

Basically I will have three beans in my application:

(1) LoginBean which in addition to handling a password etc., will have a boolean flag loggedin that is set to true if the user successfully logs in, and is reset to false when the user logs out. The state of this flag should be kept throughout the whole session, and of course the user can relogin.

(2) FormBean which handles the forms and has to know if the user is logged in. Some information in FormBean has to be passed back to LoginBean.

(3) UploadBean which enables the user to upload files to the server, and it also has to know if the user is logged in so that the user is allowed to upload files. I'm not sure yet if I have to pass information back to LoginBean, but it should be the same as above. So far I've got these beans to work correctly independently of each other, and the challenge is passing data between them, and knowing what I am doing!

Incidentally, I got the snippet of code in my previous posting to work.

Many thanks again for your help.

Christopher Sharp
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
OK, I've just got back to the problem at hand, but I'm having problems getting the code to compile. What I want to do is that LoginBean controls a page with a login form. The method checkUser() in the LoginBean below checks that the user is valid, and if there is no instance of FormBean, an instance is created by calling the last method in the class, from which the list of users in userlist is obtained. This is initialized in FormBean on startup. checkUser() returns an error code depending on the success or otherwise of logging in, which the action method uses to determine if the login is valid. Depending on this loggedin in LoginBean amd loggedin in FormBean are set accordingly.

This is what I have in my LoginBean class:



In FormBean I pass to LoginBean the contents of userlist with a getter, and pass from LoginBean to FormBean the status of loggedin.

Here is my FormBean class:



On compilation I get error messages formBean.getUserlist(), formbeansetLoggedin() etc. that the compiler cannot find the sybmol.

In following the kind advice given above, I made the method in question in LoginBean return and object that can be accessed elsewhere in the code. I would be very grateful to get help with this. I'm sure it is fairly simple, but I just don't know the correct way of doing this.

Christopher Sharp
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
In my original application at http://phoenix.ens-lyon.fr/simulator/ , after filling in the forms from the page given by the "MODEL SPECTRA" or "ISOCHRONE chi^2-fitting" buttons you then login. This is how the people here in Lyon originally wanted it, but I thought it much more sensible to make the user login first before filling in the forms.

The code at the link has since been updated locally, so what is online is already an old version even before the changes I'm trying to make at the moment.

Incidentally, "MODEL SPECTRA" is password protected as some scripts unconnected with Java are still being worked on.

Christopher Sharp
Jerwin Louise Uy
Ranch Hand

Joined: Oct 27, 2007
Posts: 75
I think this causes the problem -



Please change it to -



Regards
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
OK, many thanks, I did that, and also had to change:


to


but I now get the compilation error message that ve.getValue(el) is an incompatible type. If I just return with ve (without .getValue(el)) I still get this message, so I'm still not getting it correct.

As I may have said, I'm still not very experienced with Java, and I'm having some problems understanding how to handle and pass objects.

Christopher Sharp
Christopher Sharp
Ranch Hand

Joined: Dec 12, 2007
Posts: 155
Well, I've now changed the last line of getInstofFormBean():

i.e. casting the return object to FormBean, and the code compiles without any errors! Of course this may not be correct, so perhaps someone has some ideas while I'm testing this out to see if it works, and values can be passed between LoginBean and FormBean.

Christopher Sharp
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Passing data between beans