【问题标题】:How to keep JSF Conversations from expiring如何防止 JSF 对话过期
【发布时间】:2015-02-14 01:50:21
【问题描述】:

我需要防止 JSF 2.2 CDI 对话过期。我尝试实现一种心跳机制,在该机制中,我使用 Ajax 单击一个“隐藏”按钮,该按钮又调用一个 servlet。但对话仍然到期。出于测试目的,我将超时设置为 10 秒,我的代码如下所示。

// The begin conversation method in my managed bean
public void beginConversation() {
      if (conversation.isTransient())
      {
          conversation.setTimeout(10000);
          conversation.begin();
      }
}

// JQuery document ready function
$(document).ready(function() {
setInterval(function(){$.get("/HeartbeatServlet");}, 5000);

});

// Heartbeat servlet
@WebServlet("/HeartbeatServlet")
public class HeartbeatServlet extends HttpServlet{

private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
{
    System.out.println("Heartbeat Received");
    request.getSession();
}
}

它每 5 秒打印一次“Heartbeat Recieved”文本。但对话仍然过期。

【问题讨论】:

    标签: cdi jsf-2.2 conversation-scope


    【解决方案1】:

    对话超时是对话将保持多长时间。它不是对话的永久跟踪器。它并不意味着在请求时保持活动状态。

    没有扩展对话的概念,但是您可以使用 begin(id) 重新创建对话。该对话中的任何 bean 状态都将丢失。

    【讨论】:

    • 对于 Ajax 调用,这对我不起作用。我仍然收到错误:WELD-000321 即使我使用 begin(),也找不到恢复 id 1 的对话。如果我使用 begin(1),我会得到“对话 ID 1 已在使用中”。
    • 对话超时不是“对话将保持多长时间”,JBoss Weld 文档明确指出“超时是对话被破坏之前的不活动时间(而不是会话处于活动状态的时间)”,请参阅docs.jboss.org/weld/reference/latest/en-US/html_single/…
    【解决方案2】:

    这可能是特定于实现的,但如果您像这样做一样与begin() 开始对话,框架应该附加一个对话ID 作为请求参数。这就是将对话映射到请求的方式。

    使用焊接作为 cdi 实现,这应该是“cid”。我不知道其他实现如何处理对话。

    尝试将参数附加到您的心跳请求,它应该映射对话并可能刷新超时。

    希望对你有帮助

    【讨论】:

    • 告诉我它是否有效,我很感兴趣如果约翰·阿门特提到的对话到期...
    【解决方案3】:

    我们遇到了同样的问题。在 servlet 请求中添加“cid”没有帮助。根据我们的经验,心跳 Servlet 不知道会话。它将保持当前会话继续进行,但对会话没有帮助。

    我们的解决方案是添加一个 viewscoped managedbean,我们在其中注入 Conversation。在 UI 上,我们使用 PrimeFaces p:poll 定期调用 managebean 上的方法。

    该方法只是打印日志语句。

    @ManagedBean
    @ViewScoped
    public class ConversationListener implements Serializable {
    

    ...

    /**
     * Inject Conversation instance if it is available.
     */
    @Inject
    private Conversation conversation;
    @Inject
    FacesBroker facesBroker;
    

    ...

    /**
     * Method to refresh current conversation
     */
    public void renewConversation() {
    
        if (conversation == null) {
            System.out.println("no conversation");
        } else {
            HttpServletRequest request = (HttpServletRequest) facesBroker.getContext().getExternalContext().getRequest();
            log.info("***     ConversationListener called for conversation ID: {}", new Object[] { conversation.getId() });
            log.info("***     ConversationListener called for session ID: {}", new Object[] { request.getSession().getId() });
        }
    }
    }
    

    【讨论】:

    • 我不确定您的解决方案是否可以防止会话 bean 过期并避免 BusyConversationException,但您对“心跳 Servlet 不知道会话是绝对正确的。它将保持当前会话继续进行,但对对话没有帮助”。
    • 使用 p:poll 调用对话范围 bean 上的方法不够吗?
    【解决方案4】:

    我发现可以通过使用 Primefaces 的 p:poll 定期调用会话范围 bean 上的方法来防止会话过期,配置为使用合理的间隔(5 分钟间隔对我有用),不需要花哨的魔法。

    【讨论】:

      猜你喜欢
      • 2021-12-28
      • 2010-11-30
      • 2023-03-20
      • 2013-10-26
      • 2011-05-30
      • 2012-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多