title: How to stream a file download and display a JSF faces message?
body: <p>We are streaming a binary file to our users, following the procedure elaborated in the SO question <a href="https://stackoverflow.com/questions/9391838/how-to-stream-a-file-download-in-a-jsf-backing-bean">How to provide a file download from a JSF backing bean?</a></p>
  
  <p>In general the workflow works as intended, but during the generation of the export file <em>recoverable</em> errors may occur and we want to display these as a warning to the user. The file itself shall still be generated in that case. So we want that export to continue <em>and</em> display faces messages.</p>
  
  <p>Just to put emphasis on this: Yes, there is something not OK with the data, but our users want the export to continue and receive that flawed file anyway. Then they want to have a look at the file, contact their vendor and send him a message about the flaw.</p>
  
  <p>So I need the export to finish in any case.</p>
  
  <p>But it does not work out as we want it to. I have created a simplified example to illustrate our approach.</p>
  
  <p>As alternative we are considering a Bean that will be hold the messages and display them after the export. But probably there is a way with JSF built-in mechanisms to achieve this.</p>
  
  <p><strong>Controller</strong></p>
  
  <pre class="lang-java prettyprint-override"><code>import java.io.ByteArrayInputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import javax.faces.application.FacesMessage;
  import javax.faces.bean.ManagedBean;
  import javax.faces.bean.RequestScoped;
  import javax.faces.context.ExternalContext;
  import javax.faces.context.FacesContext;
  import org.apache.tomcat.util.http.fileupload.util.Streams;
  
  @ManagedBean
  @RequestScoped
  public class ExportController {
  
      public void export() {
          FacesContext fc = FacesContext.getCurrentInstance();
          ExternalContext ec = fc.getExternalContext();
  
          byte[] exportContent = "Hy Buddys, thanks for the help!".getBytes();
          // here something bad happens that the user should know about
          // but this message does not go out to the user
          fc.addMessage(null, new FacesMessage("record 2 was flawed"));
  
          ec.responseReset();
          ec.setResponseContentType("text/plain");
          ec.setResponseContentLength(exportContent.length);
          String attachmentName = "attachment; filename=\"export.txt\"";
          ec.setResponseHeader("Content-Disposition", attachmentName);
          try {
              OutputStream output = ec.getResponseOutputStream();
              Streams.copy(new ByteArrayInputStream(exportContent), output, false);
          } catch (IOException ex) {
              ex.printStackTrace();
          }
  
          fc.responseComplete();
      }
  }
  </code></pre>
  
  <p><strong>JSF Page</strong></p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:p="http://primefaces.org/ui"&gt;
  
      &lt;f:view contentType="text/html"&gt;
          &lt;h:body&gt;
              &lt;h:form prependId="false"&gt;
                  &lt;h:messages id="messages" /&gt;
                  &lt;h:commandButton id="download" value="Download"
                                   actionListener="#{exportController.export()}" /&gt;
              &lt;/h:form&gt;
          &lt;/h:body&gt;
      &lt;/f:view&gt;
  &lt;/html&gt;
  </code></pre>