2

I am coming to Java from Rails and PHP, so my thinking here may be tainted. I would like to implement a login system similar to ones I have done in my other systems (I understand you can manage login etc using the built in properties of Java EE, I just want to understand how I could do this manually and share objects amongst beans.)

With rails or php it is easy to maintain a session variable that holds the id of a logged in user. Then a global variable in PHP, or a property on the applicationController in rails can be pre-loaded with the user object, enabling it be available in all controllers/pages. That way the logged in status of the user and other parameters are easily accessible to all pages/controllers.

I don't know how to do a similar thing using JSF.

I know how to build a user object using JPA, and then create a managed bean with session scope that holds a reference to the user object after logging in using a loggin method from a login form. That part I understand:

@ManagedBean
@SessionScope
public class LogginController {

// inject persistence context, or use EJB to do actual loading etc
private User currentUser;     //JPA Entity

void loginAction() {
  // action from login form
  // authenticates user and loads user object into currentUser property

Where I get stuck, is that although the managed bean that contains the currentUser property has session scope, how would I access that property in other managed beans to get the current user? Managed beans seem to exist in isolation from each other.

Is the following code acceptable?

@ManagedBean
public class SomeOtherBean {

@ManagedProperty
LoginController loginController;

public void someOtherMethod() {
User myUser = loginController.getCurrentUser();
   //
   // etc

Would the class having the bean injected also have to have SessionScope too? Is this the wrong approach, would I need to manually set the session using the underlying ServletContext so that the user was accessible in other beans (i.e. save the id of the logged in user in the session, and then reload the user after accessing the user id session variable in different beans)?

Am I going about this all wrong? Is there an easier way I am missing.

simono71
  • 21
  • 1

1 Answers1

1

Is the following code acceptable?

Yes (assuming that it's pseudo; in real code it should be a private property and you should specify the managed property value like so @ManagedProperty("#{loginController}") and provide at least a setter method).


Would the class having the bean injected also have to have SessionScope too?

Not necessarily. It can perfectly be a request or view scoped bean, but not an application scoped bean (it would result in an exception). At least, you should be very careful with choosing the bean scope. Do not choose a too broad scope for the data it holds. See also How to choose the right bean scope?.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks...Would it be better to use the CDI, i.e.`@Produces @UsrNode` in the loginController and then `@UsrNode @Inject`code in the other bean? Are there any performance issues to doing things this way (using either CDI or ManagedProperty) that I should be aware of? – simono71 Feb 18 '12 at 18:19
  • That seems unnecessarily overcomplicated. Just use `@Named` and `@Inject` the same way. The CDI only offers the additional advantage that the receiver doesn't necessarily need to be of the same or shorter scope as the injected object (CDI acts namely as a proxy). By the way, if your ultimate goal is to get the current user directly as managed property without having a `LoginController` property, just use `@ManagedProperty("#{loginController.currentUser}") private User user;`. – BalusC Feb 18 '12 at 18:23
  • Awesome, how would I used `@Inject` to get the user? I thought I had to use the `@Produces` etc – simono71 Feb 18 '12 at 18:38