【问题标题】:IllegalStateException when trying to .getSessionMap() from a Session Scoped Bean尝试从 Session Scoped Bean 获取 .getSessionMap() 时出现 IllegalStateException
【发布时间】:2012-05-17 08:13:17
【问题描述】:

我是 Java 和 JSF 的新手。我需要有关 IllegalStateException 的帮助。这是场景:

在我当前的项目中,我有这个 Session Scoped bean 用于应用程序菜单:

public final class MenuBean implements Serializable{  
    private MenuModel model;
    private FacesContext context = FacesContext.getCurrentInstance();

    public MenuModel getModel() {
        return model;
    }

    public MenuBean() {
        updateMenu();
    }

    public void updateMenu(){
        Map session = (Map<String,Object>) context.getExternalContext().getSessionMap();
        EUser user = (EUser) session.get(UserBean.USER_SESSION_KEY);

        ...
    }

    private MethodExpression createMethodExpression(String action) {  
        ...  
    }
}

根据我的逻辑,我需要更新菜单,所以我这样做:

ExternalContext extContext = context.getExternalContext();
Map sMap = (Map<String,Object>) extContext.getSessionMap();

MenuBean menu = (MenuBean) sMap.get("menuBean");
menu.updateMenu();

bean 构造良好,但是当我尝试手动更新它时,如上所示,我在更新方法的第一行得到 IllegalStateException updateMenu()

我不明白出了什么问题,因为在第一次构建菜单时,我可以通过相同的调用获取会话映射。

另外,使用 NetBeans 调试器,我可以看到 MenuBean 的实例已正确恢复。

你们能帮帮我吗?

【问题讨论】:

    标签: session jsf illegalstateexception session-bean


    【解决方案1】:

    FacesContext 存储在 HTTP 请求线程中。您绝对不应该将其声明并分配为实例的实例变量,该实例的寿命比 HTTP 请求长(最好也不要在它已经基于请求的情况下 - 这是糟糕的设计)。当 HTTP 请求完成时,FacesContext 实例被释放并失效。在任何后续 HTTP 请求中,该实例不再有效。有非法状态的手段。这解释了您所看到的IllegalStateException

    您需要删除以下行:

    private FacesContext context = FacesContext.getCurrentInstance();
    

    并修复您的代码,使其仅在方法块中使用线程本地:

    Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
    // ...
    

    您始终可以将其分配为变量,但只能保持线程本地化:

    FacesContext context = FacesContext.getCurrentInstance();
    Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
    // ...
    

    与具体问题无关,在这种特殊情况下使用@ManagedProperty 更容易。

    public final class MenuBean implements Serializable {  
    
        @ManagedProperty("#{user}")
        private EUser user;
    
        // ...
    }
    

    JSF 然后会为你注入它。

    【讨论】:

    • 嗨 BalusC。非常感谢。那解决了它。我在教程中看到了那个(糟糕的)设计,但后来我改变了我的 bean 的范围,并没有注意到这可能发生。
    • 我不太明白@ManagedProperty 是如何工作的。容器将如何解析 "#{user}" ?我必须定义这个吗?
    • 它只是评估EL表达式并在MenuBean构造后直接使用检索到的对象调用getter方法。这里我假设您的UserBean.USER_SESSION_KEY 的值为user,因此它在EL 范围内有效地作为#{user} 提供。
    • 我明白了。但据我了解 JSF 中的东西,这个 EL 表达式不应该像 "#{userBean.user}" 吗?
    • 我不知道,因为您的代码中不存在此细节,因为您正在使用常量。但它应该与您在 UserBean.USER_SESSION_KEY 中的属性名称和您在 XHTML 文件中用于从会话范围获取用户的 EL 表达式相同。
    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-09
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 2020-10-22
    相关资源
    最近更新 更多