JSF RequestContext.execute被评估两次

时间:2017-05-23 18:35:30

标签: java jsf primefaces

在我的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>

爪哇:

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 + "');");
    }
}

这是一个有希望澄清逻辑流程的流程图: Flowchart

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

[更新:5/24/17]
我怀疑,作为JSF的完全新手,我没有正确使用actionListeners和remoteCommands。 @BalusC有几个回应&amp;像thisthis这样的文章表明这​​可能是一个范围问题。

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

1 个答案:

答案 0 :(得分:0)

如果遇到其他人,我通过将bean的javascript回调移动到oncomplete的{​​{1}}属性来解决它。它现在看起来像这样:

JSF:

commandButton

爪哇:

<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>