JSF Я теряю состояние сеанса при переходе с управляемого на CDI

Изменить: это эпическая ситуация с ладонью лица. Неправильный импорт для SessionScoped. Прошлой ночью я так устал, проверяя его, что был уверен, что использую импорт в корпоративном режиме с сохранением сеанса, в то время как все еще использую импорт лиц с сеансом. Я оставляю это в помощь глупцам вроде меня. :)


Это начало этого проекта. После реализации до этого момента с управляемыми bean-компонентами я изменил свои управляемые bean-компоненты на bean-компоненты CDI, поскольку это, по-видимому, последний консенсус в отношении наилучшего способа решения задач Но это нарушило ранее работавший код. Я не могу. хоть убей выяснить, почему. Помощь и совет приветствуются.

Счастливый путь (Сводка ... подробности ниже отрывки кода)

Если пользователь не вошел в систему, отобразить ссылки для входа или регистрации.
Если пользователь вошел в систему, отобразить настройки пользователя или ссылки для выхода.

Теперь Crappy Path с CDI (я не виню CDI)

Если пользователь не вошел в систему, показать ссылки для входа или регистрации.
Если пользователь вошел в систему, он все равно будет видеть ссылки для входа или регистрации. (плохое, плохое приложение)

Вовлеченные объекты:

  1. панель меню Facelet (с диалоговым окном входа в систему Primefaces ... Я не думаю, что это имеет к этому какое-либо отношение, но включено для полноты) с атрибутами рендеринга, если вы вошли в систему или нет,
  2. пользовательский компонент с ограничением сеанса,
  3. bean-компонент аутентификации с ограниченным объемом запроса для входа и выхода пользователя.

Используемые объекты перечислены ниже. Реализован как bean-компоненты CDI.

лицо

<h:panelGroup id="loginPanel" rendered="#{!user.loggedIn}">
    Show login buttons and stuff
</h:panelGroup>

 <h:panelGroup id="logoutPanel" rendered="#{user.loggedIn}">
    Show logout buttons and stuff
</h:panelGroup

компонент аутентификации

@Named(value = "webAuthenticationBean") //formerly managedbean
@RequestScoped
public class WebAuthenticationBean implements Serializable {

    @Inject private UserBean user; //formerly a managed property which worked
...
request.login(uername, password);
user.setuserdata(username); // sessionscoped user state here used to check login state among other things later.
...
return(true) // they are now logged in

пользовательский компонент

@Named(value = "user") //formerly managedbean
@SessionScoped
public class UserBean implements Serializable {

    @EJB
    private UserService userService; //stateless session bean
    private userInfo = new UserInfo(); // keeps user state and can be used as a DTO/VO

@PostConstruct
    public void init() {
    //sets default state to "guest user". This is NOT a logged in state
    }

public void setuserdata(String username){
     userInfo = userService.getUserInfo(username);
    // method called from WebAuthenticationBean 
    // sets the user state to a non-guest user (they're logged in).
    // I can see in debug mode that this is being called and retrieving
   //  the user data from the database and setting "userInfo"
}

public void isLoggedIn() throws InvalidUserException{
    // checks state to see if they are logged in, basically a bit more than are they still a guest or not
   returns (true) if logged in 
    returns (false) if not logged in
    // this worked with managed beans
}
...

Итак, вот реальный вариант использования, когда я смотрю в режиме отладки:

Счастливый путь (до перехода на компонент CDI)

1) Пользователь переходит на страницу приветствия.
2) пользовательский компонент запрашивает, вошли ли они в систему (user.loggedIn в фейсе).
3) userbean проверяет состояние входа в систему. Если они все еще гость, они не вошли в систему.
4) Они идентифицированы как гость, поэтому isLoggedIn () возвращает false.
5) Отображается кнопка входа.
6) Пользователь запрашивает журналы в
7) bean-компонент аутентификации начинает процесс входа в систему: request.login успешно возвращается
8) authenticationbean устанавливает данные пользователя: user.setuserdata (username) возвращается успешно.
9) bean-компонент аутентификации loginMethod возвращает (они зарегистрированы как главный пользователь на сервере)

Альтернативный (дрянной) ветвь пути здесь (счастливый путь продолжается)

10) Меню перепроверяет состояние входа в систему (user.loggedIn)
11) userbean проверяет соответствующее состояние и видит, что они являются действительными пользователями, не являющимися гостями
12) userbean возвращает (true) они вошли в систему
13) в меню отображается кнопка выхода

Crappy Path (что происходит после того, как я изменил их на bean-компоненты CDI)

10) Меню повторно проверяет состояние входа в систему (user.loggedIn)
11) userbean проверяет соответствующее состояние и видит, что он гость // обновленное состояние пользователя, похоже, исчезло у этого пользователя в этом сеансе.
12) userbean возвращает (false) они не вошли в систему // но они есть
13) в меню отображается кнопка входа // они все равно не могут войти, так как сервер уже видит их как вошедших в этот сеанс (ServletException : Попытка повторно войти в систему, пока идентификатор пользователя уже существует).

Почему с помощью managedbeans я мог бы видеть, что userbean поддерживает свои данные в области сеанса, а с cdi beans - нет? Я в тупике. Я вернусь к управляемым бобам, если потребуется, это не большая проблема, но я хотел бы выяснить, что я напутал.




Я добавил отладочный код в метод инициализации UserBean, и похоже, что система обрабатывает SessionScoped UserBean, как если бы он был RequestScoped. То есть он инициализируется при каждом вызове.

@PostConstruct
public void init() {
    if (userInfo == null) {
        userInfo = new UserInfoDTO();
        userInfo.setUserName("Guest");
        List<String> guestGroup = Arrays.asList(CoreUserGroupType.GUEST.toString());
        userInfo.setUserGroups(guestGroup);
        System.out.println("UserBean.init INSIDE Init If Statement");
    }
    System.out.println("UserBean.init OUTSIDE Init If Statement");
}

Если бы он действительно действовал так, как будто был SessionScoped, объект userInfo не был бы нулевым каждый раз, и оператор if не выполнялся бы каждый раз. Но он выполняется при каждом вызове UserBean. Так что в этом суть проблемы. Фактически, если бы он действовал так, как будто находился в области сеанса, он вообще не попадал бы в метод init при каждом вызове, поскольку он все равно инициализировался бы.

Я неправильно создаю bean-компонент с ограничением сеанса? Казалось бы, да, но я не понимаю, как это сделать. Как уже упоминалось, этот код работал нормально, когда был определен как управляемый бин.


person Bill Rosmus    schedule 20.08.2012    source источник


Ответы (1)


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

person Bill Rosmus    schedule 20.08.2012
comment
Я думаю, мы все это сделали, и хорошо, что ты пришел честно. - person Oversteer; 21.08.2012
comment
Сбивает с толку то, что в Java EE есть эти две аннотации. Последнее, что я слышал, это то, что Face One будет устаревшим. Хотя это может занять много времени ... - person Mike Braun; 22.08.2012