0

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

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

我有一个由 JPA 管理的对象 - 让我们称之为 X(实现可序列化)我有一个范围为会话映射的 bean - 让我们称之为 Y(实现可序列化)

我的 Y 类如下所示。

@SessionScoped
class Y implements Serializable
{
  private X selectedObject;

  // Getter & setter for X
}

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

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

关于这里可能出了什么问题的任何想法?

谢谢,哈沙

4

1 回答 1

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;
    }
}
于 2013-08-06T20:25:50.803 回答