2 Replies Latest reply: Feb 1, 2013 12:12 PM by Dave.Jarvis RSS

    Prevent af:fileDownloadActionListener action event

    Dave.Jarvis
      # Background

      The following problem is also described at: http://stackoverflow.com/questions/14638103/prevent-affiledownloadactionlistener-action-event

      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:

      - http://jobinesh.blogspot.ca/2010/01/customizing-execution-of-to-validate.html
      - http://tompeez.wordpress.com/2011/07/14/validate-data-before-export-via-afexportcollectionactionlistener-or-affiledownloadactionlistener/

      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?

      Thank you!