从Session Scoped Bean尝试.getSessionMap()时出现IllegalStateException

时间:2012-05-08 19:51:39

标签: session jsf illegalstateexception session-bean

我是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构造正常,但是当我尝试手动更新它时如上所示,我在更新方法updateMenu()

的第一行得到和IllegalStateException

我不明白错误,因为我可以在第一次创建菜单时使用相同的调用获取会话映射。

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

你们能帮助我吗?

1 个答案:

答案 0 :(得分:2)

FacesContext存储在HTTP请求线程中。您绝对不应该声明并将其指定为一个实例的实例变量,该实例的生命周期比HTTP请求长(并且最好也不是当它已经基于请求时 - 它的设计不好)。 HTTP请求完成后,FacesContext实例将被释放并失效。在任何后续HTTP请求中,实例都不再有效。有非法国家的手段。这解释了您所看到的IllegalStateException

您需要删除以下一行:

private FacesContext context = FacesContext.getCurrentInstance();

修复你的代码,使其只在方法块中获得threadlocal:

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

您始终可以将其指定为变量,但只能保留threadlocal:

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

对于具体问题

无关,在这种特殊情况下使用@ManagedProperty变得更加容易。

public final class MenuBean implements Serializable {  

    @ManagedProperty("#{user}")
    private EUser user;

    // ...
}

然后JSF会为你注入它。