Update component after file download

I'm using Primefaces TabView, CommandButton and FileDownload to download a log file. Once the log file has been downloaded, I want to offer the option to delete the contents of the log from the server.

Initially the Delete Log File Button (deleteEventLogButton) is disabled and has a custom caption stating "Delete Logs - Export Required". Once the log has been exported, the button should be enabled and the caption should state "Delete Logs".

The problem that I'm having is that the Delete Log File Button is still disabled and the caption reads "Delete Logs - Export Required" even after the Export event completes successfully.

My guess is that the exportEventLogButton->Update="deleteEventLogButton" is being called before the fileDownload value.

Once I've exported the logs, I can hit 'F5' and refresh the page and the deleteEventLogButton is enabled showing the correct caption.

JSF - Snippet

<p:tabView id="logView">
    <p:tab id="eventLogTab" title="Security Events">
        <p:panelGrid ...>

            <p:commandButton id="exportEventLogButton" icon="ui-icon-disk" styleClass="c25" ajax="false" title="Export Log" disabled="#{empty managedCmsLogsBean.eventLogEntityList}" update="deleteEventLogButton">
                <p:fileDownload value="#{managedCmsLogsBean.exportEventLogFiles()}"/>
            </p:commandButton>

            <p:commandButton id="deleteEventLogButton" icon="ui-icon-trash" styleClass="c25" ajax="false" title="#{managedCmsLogsBean.deleteEventLogCaption}" disabled="#{! managedCmsLogsBean.eventLogExported}" action="#{managedCmsLogsBean.clearEventLogs()}" update="eventLogTab" />    

        </p:panelGrid>

        <p:dataTable value="#{managedCmsLogsBean.eventLogEntityList}" ...>
            ...
        </p:dataTable>

    </p:tab>
</p:tabView>

Backing Bean - Snippet

private boolean eventLogExported;

public StreamedContent exportEventLogFiles() {
    eventLogExported = true;
    return logFileUtility.exportSecurityEventLog(eventLogEntityList, eventLogStartDate, eventLogStopDate);
}

public boolean isEventLogExported() {
    return eventLogExported;
}

public void setEventLogExported(boolean value) {
    eventLogExported = value;
}

public String getDeleteEventLogCaption() {
    return eventLogExported ? "Delete Logs" : "Delete Logs - Export Required";
}

I tried moving the update event inside the FileDownload, but it didn't make a difference.

<p:commandButton id="exportEventLogButton" icon="ui-icon-disk" styleClass="c25" ajax="false" title="Export Log" disabled="#{empty managedCmsLogsBean.eventLogEntityList}">
    <p:fileDownload value="#{managedCmsLogsBean.exportEventLogFiles()}">
        <p:ajax update="deleteEventLogButton"/>
    </p:fileDownload>
</p:commandButton>

I've searched for a couple of days now and have found MANY problems that come very close to this one... but none that have helped. :(

Just to make things very clear... I am NOT having problems with the export. The problem is that the Delete Log File Button is not enabled after the export is complete.


Solution 1:

p:commandButton in your case is (an has to be) non-AJAX button (you set this by adding ajax="false" attribute). In that case update attribute and p:ajax tag doesn't have any sense (as they are only for AJAX requests). When you have file download your application sends streaming of some type, and you see Save File dialog. Your page is not refreshed. So you have to use PrimeFaces.monitorDownload to do this:

<p:commandButton id="exportEventLogButton" 
                 icon="ui-icon-disk" 
                 styleClass="c25" 
                 ajax="false" 
                 title="Export Log" 
                 disabled="#{empty managedCmsLogsBean.eventLogEntityList}"
                 onclick="PrimeFaces.monitorDownload(null, stop)">

and add stop function which will update second button:

<p:remoteCommand name="stop" update="deleteEventLogButton"/>

Solution 2:

As Balusc answered, In question (revisions) , we cannot get response twice from a single request, to refresh a page after download, better use the following java script in download link(p:commandbutton) onclick tag.

Example:

<p:commandButton ajax="false" icon="ui-icon-arrowstop-1-s" onclick="setTimeout('location.reload();', 1000);" action="#{managedBean.downloadMethod}" />

this will automatically refresh the page after 1 second, at the same time i.e. before refresh, you will get the download file, based on your download response time, increase the seconds in that script. Seconds should not less than that download response time.

Solution 3:

From PrimeFaces 10, you are able to download files with ajax="true". This allows you to update components as well.

See also:

  • https://primefaces.github.io/primefaces/10_0_0/#/components/filedownload?id=ajax-downloading
  • https://github.com/primefaces/primefaces/issues/5978