Обновление вида бобов JSF, введенных в область видимости

@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 включают элементы управления входом практически на каждой странице. Идеальным было бы, чтобы они могли войти, и страница обновится, а существующие FooController будет иметь ссылку на текущего вошедшего в систему пользователя, который условно отображает кнопки / элементы. Поведение состоит в том, что вход в систему происходит, но FooController view по-прежнему "действителен", поэтому управляемый бин никогда не будет пытаться внедриться снова. Если я перейду со страницы и вернусь на нее [восстанавливаю bean-объект области видимости], пользовательский bean-компонент будет добавлен заново... но я бы предпочел, чтобы этот промежуточный шаг не выполнялся. Есть идеи?

Я пробовал различные формы FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove("user"); в надежде, что он вытащит его из сессии, но безрезультатно. Я не хочу тесно связывать код в моем LoginController, чтобы ссылаться на недействительную FooController, BarController или любую другую, ссылающуюся на пользовательский компонент.

2 ответа

Решение

Хорошо, я понял это по дороге домой, это была проблема жизненного цикла. Я пытался заставить JSF сделать что-то, чего не следует делать с управляемыми бинами.

Вместо нового User объект и переназначить его на управляемый экземпляр user в LoginController, я изменил метод входа в систему, чтобы выглядеть так:

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";
}

Это завершает то, что было необходимо. Кто бы знал, если вы прекратите бороться с фреймворком на минуту и ​​просто используете его, это поможет вам:)

Почему вы пытаетесь удалить user@SessionBean), от viewMap (карта @ViewScoped объекты в текущем сеансе)?

Вы должны удалить FooController, @ViewScopedфасоль из viewMapт.е.

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

Это то, что избавит от видоизмененного боба и заставит создать новый. Тогда, конечно, вам все равно придется обновить страницу.

Если вы намереваетесь удалить сессионный компонент, вы должны получить прямой доступ к сеансу:

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

Это избавляет от объекта пользователя

Другие вопросы по тегам