Pregunta

Background

Using JDeveloper 11.1.2.3 to create a report download button using fileDownloadActionListener as follows:

<af:commandButton text="Run Report" id="submitReport">
  <af:fileDownloadActionListener method="#{reportBean.run}"/>
</af:commandButton>

At the top of this JSF page is the following:

<f:view afterPhase="#{validationBean.afterPhase}" ...>
  ...
    <af:form id="f1">
      <f:event listener="#{validationBean.postValidate}" type="postValidate"/>

The idea is that the Validation Bean can capture any validation problems as follows:

public void afterPhase(javax.faces.event.PhaseEvent phaseEvent) {
  if (phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE) {
    FacesContext context = phaseEvent.getFacesContext();
    FacesMessage.Severity severity = context.getMaximumSeverity();

    if (isSevereError(severity)) {
      context.getExternalContext().getSessionMap().put(ERROR_FLAG_NAME, true);
    }
  }
}

This works as expected. When the user presses the button, but the form has an error, the validationError session variable is set to true. This should allow the framework to prevent the report from being generated if the form parameters have errors.

Problem

The validationError session variable is used by the report bean's run method as follows:

  public void run(FacesContext facesContext, OutputStream outputStream) {
    Object error = facesContext.getExternalContext().getSessionMap().get( ERROR_FLAG_NAME );

    if( error != null && error != Boolean.TRUE ) {
      Report report = null;

      try {
        report = getReport();
        report.setOutputStream(outputStream);
        configure(report.getParameters());
        report.run();
      } catch (Exception e) {
        if (report != null && facesContext != null) {
          report.publish(e);
        }
      }
    }
    else {
      facesContext.getExternalContext().getSessionMap().remove( ERROR_FLAG_NAME );
      facesContext.renderResponse();
    }
  }

When there is a validation error in the page, the facesContext.renderResponse(); code is executed, but the resulting web page is blank. No exceptions are logged. No errors are generated.

Question

One way to avoid this situation uses a hidden button, custom Java, and some JavaScript, as described on the following pages:

However, that mechanism is complicated. The solution I have in mind will work if the page can be rendered as usual.

How do you force the page to be rendered after the af:fileDownloadActionListener event has fired?

¿Fue útil?

Solución

Frank Nimphius said:

using a hidden button is the only option you have available today. I will file an ER that raises an event for the fileDownload listener (sort of a pre-download) that should allow you to cancel it by calling Render Response. As said, this doesn't exist yet and the hidden button is the option you have available (note that the file download tag is a client behavior tag and not a full UI component, which is why there is no way yet to interrupt execution.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top