1

我是 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 构造良好,但是当我尝试手动更新它时,如上所示,我在更新方法的第一行得到 IllegalStateExceptionupdateMenu()

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

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

你们能帮帮我吗?

4

1 回答 1

2

FacesContext存储在 HTTP 请求线程中。您绝对不应该将其声明并分配为实例的实例变量,该实例的寿命比 HTTP 请求长(最好也不要在它已经基于请求的情况下 - 这是糟糕的设计)。当FacesContextHTTP 请求完成时,实例被释放并失效。在任何后续 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 将为您注入它。

于 2012-05-08T21:38:50.283 回答