JSFのアクションで独自の出力を行うには

JavaServer FacesCSV,PDFなどをダウンロードするためのアクションは、こんな風にするとよい。

@In private FacesContext facesContext;

public String someAction() {
    String encoding = "Windows-31J";
    String filename = getFilename(); // ファイル名を取得する。
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
    response.setContentType("application/octet-stream; charset=" + encoding);
    response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
    response.setCharacterEncoding(encoding);
    PrintWriter writer = response.getWriter();
    writeCsvData(writer); // writerに出力する。
    facesContext.responseComplete();
    return null;
}

ポイントはFacesContext.responseComplete()で、これを呼んでおくとRenderResponseフェーズがスキップされる。