Бин с состоянием: serlvet принимает неправильное значение, тогда как управляемый Бин не

У меня есть Stateful Session Bean который содержит мой сеанс входа в систему, JSF Session Bean и Servlet Filter,

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

doFilter() это вот так:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    String path = req.getRequestURI().substring(req.getContextPath().length());
    System.out.println(userManager.isLogged());
    if (userManager.isLogged() || path.equals("/") || path.equals("/index.xhtml") || path.startsWith(ResourceHandler.RESOURCE_IDENTIFIER) || path.startsWith("/resources/") || path.startsWith("/admin") || path.equals("/admin/login.xhtml")) {
        chain.doFilter(request, response);
    } else {
        request.getRequestDispatcher("/error.xhtml").forward(request, response);
    }
}

где userManager находится с:

private UserManagerLocal lookupUserManagerLocal() {
    try {
        Context c = new InitialContext();
        return (UserManagerLocal) c.lookup("java:global/UNILIFE/UNILIFE-ejb/UserManager!ejb.UserManagerLocal");
    } catch (NamingException ne) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
        throw new RuntimeException(ne);
    }
}

Сейчас, System.out.println(userManager.isLogged()); печатает всегда ложно, в то время как #{loginBean.logged} печатает правда.

Обратите внимание, что loginBean.logged просто

public boolean isLogged() {
    return userManager.isLogged();
}

и в моем управляемом бобе, userManager извлекается с

@EJB
private UserManagerLocal userManager;

Похоже, что сервлет не принимает тот же SFSB, что и управляемый компонент JSF.

Что я делаю неправильно?

РЕДАКТИРОВАТЬ: новый код

сервлет

UserManagerLocal userManager = lookupUserManagerLocal();
private UserManagerLocal lookupUserManagerLocal() {
    try {
        Context c = new InitialContext();
        UserManagerLocal userM = (UserManagerLocal) c.lookup("java:global/UNILIFE/UNILIFE-ejb/UserManager!ejb.UserManagerLocal");
        HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
        req.setAttribute("userManager", userM);
        return userM;
    } catch (NamingException ne) {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception caught", ne);
        throw new RuntimeException(ne);
    }
}

JSF бин

@PostConstruct
public void init(){
    HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
    userManager = (UserManagerLocal) req.getSession().getAttribute("userManager");
}

2 ответа

Каждый раз, когда вы просматриваете сессионный компонент с сохранением состояния, вы создаете уникальный экземпляр, поэтому isLogged, вероятно, возвращает значение поля по умолчанию. Вам нужно каким-то образом сохранить экземпляр сессионного компонента с состоянием в HttpSession и извлечь его из вашего фильтра. Мне не хватает опыта работы с JSF, поэтому я не знаю, есть ли удобный способ поделиться экземпляром сессионного компонента с сохранением состояния или вам нужно вручную связать JSF-компонент с компонентом с состоянием.

Каждый поиск JNDI будет возвращать новый дескриптор бобу. Поэтому вы получаете значение по умолчанию при вызове метода, отбрасывая предыдущие действия. Вам нужно сохранить эту ссылку (HttpSession) для дальнейших операций над ней, как объяснено в другом посте.

Ниже приведен пример кода для доступа к сеансу в бине JSF.

HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();

Из запроса вы можете получить сессию и затем разместить в ней.

session.setAttribute("userManager", userManager);

Теперь в фильтре вы можете получить бин из запроса. Кроме того, измените код соответственно.

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