GAE / J:尽管可序列化,但有些对象在会话中没有持久存在

时间:2013-08-06 16:36:56

标签: google-app-engine jsf-2

我在GAE / J中有一个非常奇怪的问题。事情在本地环境中起作用,但在GAE服务器上不起作用。

环境:GAE / J 1.8.2 + JSF 2.2.1 + JPA

我有一个由JPA管理的对象 - 让我们称之为X(实现Serializable) 我有一个限定为会话映射的bean - 让我们称之为Y(实现Serializable)

我的班级Y如下所示。

@SessionScoped
class Y implements Serializable
{
  private X selectedObject;

  // Getter & setter for X
}

作为操作的一部分,我设置X的值,然后将用户重定向到另一个页面。当我在第二页中访问bean时,它告诉我没有为X设置任何值。

现在,我的猜测是由于某种原因,GAE没有在数据存储区支持的会话中将此引用存储到X.我尝试了各种日志记录,但我无法弄清楚为什么只有X(一个JPA实体)没有与对象的其余部分一起持久化到会话范围。

这里可能出现什么问题的想法?

谢谢, 戒日

1 个答案:

答案 0 :(得分:0)

发现了这个问题。所以我知道为了避免ViewExpiredException,其中一种方法是设置一个阶段监听器,它将随机属性更新到会话映射中,从而强制将映射序列化到数据存储。我做的一个错误就是让这个阶段监听器在RENDER_RESPONSE阶段的afterPhase()中完成这项工作。

我忘记考虑的事实是在INVOKE_APPLICATION阶段发生了面部重定向...这意味着我的侦听器从未在重定向情况下被调用。

将侦听器更改为ANY_PHASE并显式更新INVOKE_APPLICATION或RENDER_RESPONSE的会话映射后,我现在看到了预期的结果。

示例代码供您参考。

public class SessionSerializationListener implements PhaseListener
{
    @Override
    public void afterPhase(PhaseEvent event)
    {
        // Set an attribute on to the session just so that we can force the session to get serialized
        // We target the invoke application phase as well since the redirects get issued in that phase
        if (event.getPhaseId() == PhaseId.INVOKE_APPLICATION || event.getPhaseId() == PhaseId.RENDER_RESPONSE)
        {
            // get hold of the session map
            sessionMap.put("__timestamp__", System.currentTimeMillis());
        }
    }

    @Override
    public void beforePhase(PhaseEvent event)
    {
        // Do nothing.
    }

    @Override
    public PhaseId getPhaseId()
    {
        return PhaseId.ANY_PHASE;
    }
}