【问题标题】:JSF RequestContext.execute being evaluated twiceJSF RequestContext.execute 被评估两次
【发布时间】:2017-10-23 20:43:58
【问题描述】:

在我的 PrimeFaces 应用程序中,我正在生成一个文件以供下载。一代开始了,然后我进入一个等待循环,直到它准备好。现在看来,这个循环被启动了两次。代码如下:

JSF:

<p:commandButton id="downloadBtn" value="Download" disabled="#{bean.selectedRow == null}"
    onclick="blockUI()"
    actionListener="#{bean.generateFileAndDownloadWhenReady()}"/>

<script type="text/javascript">
  function downloadFileWhenReady(key) { 
    window.setTimeout(function () {
            checkForDownloadReady([{name:"key",value: key }]);                            
        }, 1000);
  }

  function doTheActualDownload(key) {
    // handle the download
  }
</script>

Java:

public void generateFileAndDownloadWhenReady() {
    key = kickoffFileGeneration();
    RequestContext.getCurrentInstance().execute("downloadFileWhenReady('" + key + "');");
}


public void checkForDownloadReady() {
    String key = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("key");
    STATUS status = FileCache.getFileStatus(key);

    if (status == STATUS.READY) {
        RequestContext.getCurrentInstance().execute("doTheActualDownload(" + key + ");");

    } else if (status == STATUS.FAILED) {
        logger.error("Failure creating file. Wail loop will end.");

    } else if (status == STATUS.OPEN){
        RequestContext.getCurrentInstance().execute("downloadFileWhenReady('" + key + "');");
    }
}

这是一个流程图,希望能阐明逻辑流程:

通过在 generateFileAndDownloadWhenReady() 中放置断点,我可以看到它只被调用一次,但在 downloadFileWhenReady() 中的断点被调用了两次。通过使用长循环延迟,我知道第二个调用不是来自循环。此外,对 kickoffFileGeneration() 的调用非常快——它为实际工作启动了一个新线程。那么为什么它会被调用两次,我该如何阻止它呢?

[更新:2017 年 5 月 24 日]
我怀疑,作为 JSF 的新手,我没有正确使用 actionListeners 和 remoteCommands。 @BalusC 有几个回复和文章,例如 this 和 this,这表明这可能是一个范围界定问题。

并回答为什么我不只是简单地从 commandButton actionListener 返回文件的问题,这是因为生成 .zip 文件可能需要几分钟时间。因此,我通过分离工作线程来避免阻塞 UI,并且我还使用 &lt;p:blockUI&gt; 元素来娱乐用户。

【问题讨论】:

  • 那么最好学习“推送”而不是实现自己的轮询机制,最好不要创建自己的线程。搜索如何在现代 Web 应用中执行异步操作
  • 感谢@Kukeltje 的提示。我确实调查过它,但读到并非所有浏览器都支持“推送”,所以无论如何我都必须有一个轮询后备。我也不喜欢投票,所以下次我会记住这一点。 (此外,这是一个低流量的私人应用程序,希望能减少它的罪恶。);-)
  • 定义'所有浏览器'...当前的FF、Chrome和IE都支持它。如果不是,他们会退回到长轮询,这正是您要实现的目标

标签: java jsf primefaces


【解决方案1】:

如果其他人遇到这种情况,我通过将 javascript 回调从 bean 移动到 commandButton 的 oncomplete 属性来解决它。现在看起来像这样:

JSF:

<p:commandButton id="downloadBtn" value="Download" disabled="#{bean.selectedRow == null}"
       onclick="blockUI()" oncomplete="downloadFileWhenReady()"
       actionListener="#{bean.generateFile()}"/>

<p:remoteCommand name="checkForDownloadReady" actionListener="#{bean.checkForDownloadReady}"/>

<!-- Hidden button to contain the fileDownload element -->
<p:commandButton id="downloadFile" ajax="false" style="display:none"  onclick="releaseUI();">
    <p:fileDownload value="#{bean.file}" contentDisposition="attachment"/>
</p:commandButton>

<script type="text/javascript">
    function downloadFileWhenReady() {
        window.setTimeout(function () {checkForDownloadReady();}, 1000);
    }        
    function doTheActualDownload() {
        document.getElementById('the_form:downloadFile').click();
    }
    function blockUI() {
        PF('blocker').show();
    }
    function releaseUI() {
        PF('blocker').hide();
    }
</script>

Java:

private String key;

public void generateFile() {
    key = kickoffFileGeneration();  // spawns worker thread, creates file in FileCache
}

public void checkForDownloadReady() {
    STATUS status = FileCache.getFileStatus(key);

    if (status == STATUS.READY) {
        FileCache.setFileStatus(key, STATUS.HANDLED);
        RequestContext.getCurrentInstance().execute("doTheActualDownload()");

    } else if (status == STATUS.FAILED) {
        logger.error("Failure creating file. Wait loop will end.");

    } else if (status == STATUS.OPEN || status == STATUS.NEW){
        RequestContext.getCurrentInstance().execute("downloadFileWhenReady()");
    } 
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多