Question

@SessionScoped public class User {
...  //settings, attributes, etc
}

@ViewScoped public class FooController {
@ManagedProperty(value="#{user}") 
private User user;
...
}

@RequestScoped public class LoginController {
@ManagedProperty(value="#{user}") 
private User user;
public String login() {
    //handle Servlet 3.0 based authenticate()... if success, make new User object and slap it into context
    request.getSession().setAttribute("user", user);
    return "?faces-redirect=true";
}
...
}

xhtml pages include the login controls on pretty much every page. The ideal would be that they are able to login, and the page will refresh and the existing FooController would have the reference to the currently logged in user, which conditionally renders buttons / elements. The behavior is that the login occurs, but the FooController view is still "valid", so the managed bean never is attempted to be injected again. If I navigate off the page, and back onto it [reconstructing the view scoped bean] the user bean is reinjected nicely... but I'd prefer not to have that interim step. Any ideas?

I've tried various forms of FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove("user"); in hopes that it will re-pull it from session but no avail. I do not want to tightly couple code in my LoginController to reference specifically invalidating a FooController or BarController or any other that refs the user bean.

Was it helpful?

Solution 2

Ok, I figured this out on the drive home, it was a lifecycle problem. I was trying to get JSF to do something it shouldn't be doing to managed beans.

Instead of new'ing up a User object and reassigning it to the managed instance of user in LoginController, i changed the login method to look like this:

public String login() {
  //handle Servlet 3.0 based authenticate()... if success...
  User loadedFromDB = someDao.load(principal.getName());
  user.setDefaultPage(loadedFromDB.getDefaultPage());  // NOTE:  The user object IS THE MANAGED BEAN
  user.setDefaultScheme(loadedFromDB.getDefaultScheme());  //  This is the same object the view scoped bean has a ref on, so directly setting that object's fields proliferates that to any other bean that has the user in scope.
  ... //etc... not calling NEW, not reassigning object ref to user
  loadedFromDB = null;
  return "?faces-redirect=true";
}

This accomplishes what was needed. Who knew, if you stop fighting the framework for a minute and just use it, it helps you out :)

OTHER TIPS

Why are you trying to remove user (a @SessionBean), from the viewMap (a map of @ViewScoped objects in the current session)?

You should be removing FooController, the @ViewScoped, bean from the viewMap, i.e.

FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove("fooControl‌​ler");. 

This is what will get rid of the viewscoped bean and force a new one to be created. Then of course, you'll need to refresh the page anyway.

If you're intent on removing the session bean however, you should be accessing the session directly:

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("user");.

That gets rid of the user object

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top