Обновить введенный компонент JSF bean-компонентов с областью представления

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

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


person Eric    schedule 26.11.2013    source источник


Ответы (2)


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

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

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

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

Однако, если вы намерены удалить сессионный компонент, вы должны напрямую обращаться к сеансу:

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

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

person kolossus    schedule 26.11.2013
comment
Что ж, цель состоит не столько в том, чтобы удалить пользовательский компонент, сколько в том, чтобы распространить обновленный объект User на любой компонент с областью видимости. Я протестировал ваше решение, которое работает, но FooController является лишь одним из примерно 20 bean-компонентов с областью видимости, которые могут быть активны в зависимости от того, с какой страницы пользователь входит в систему. [Форма входа представляет собой всплывающую панель, которая присутствует почти на каждой странице]. Казалось бы, проблема запутанности состоит в том, что кодовое имя LoginController содержит более 20 bean-компонентов, которые нужно попытаться удалить. - person Eric; 27.11.2013

Хорошо, я понял это по дороге домой, это была проблема жизненного цикла. Я пытался заставить 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";
}

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

person Eric    schedule 27.11.2013