Jochen, If you are refering to streaming a file- I have struggled with the same thing. For some reason this breaks the JSF lifecycle. I have however come up with a solution that uses a hidden iframe. This approach allows JSF to finish its lifecycle without being affected by the file being streamed for download.
This is how it works... In your request scoped bean (ReportBean.java) where we want to download a file from (in my case it was a report) I have a method that invokes the download. It sets the temporary session attribute that holds the report/file by calling the static method "FileDownloadBean.setFileForDownload(report);" and sets an property of the bean that holds the url to the "fileDownload.jsp" using "setReportDownloadUrl("fileDownload.jsp");" (by default this propertys getter method returns "about:blank" to the iframe src). When these two methods are called in your bean the "reportDownloadUrl" getter method will return the proper url to the "fileDownload.jsp" page invoking the "FileDownloadBean.java" constructor that invokes the file download process to the iframe. I also added an error message in case things go wrong. Because we are using a hidden iframe that has no knowledge of the page that invoked it we can't use the regular faces messages. However, we can use a simple JavaScript alert that uses a message resource bundle message. The source code: reportResult.jsp (the page we want to download a file from insert the following- css class "file-download" just sets "visibility:hidden;display:none;"): ... <t:panelGroup id="fileDownloadPanel" binding="#{report.fileDownloadPanel}"> <f:verbatim> <iframe id="fileDownloadFrame" frameborder="0" scrolling="0" src="</f:verbatim><tr:outputText value="#{report.reportDownloadUrl}" /><f:verbatim>" class="file-download"></iframe> </f:verbatim> </t:panelGroup> ... fileDownload.jsp (I use myfaces base form and command button, but tr should work as well): <f:view> <f:loadBundle basename="WEB-INF.resources.message" var="labels" /> <t:panelGroup rendered="#{!fileDownload.isComplete}"> <trh:html> <trh:body onload="#{fileDownload.clientScriptError}"> <h:form id="fFileDownload"> <h:commandButton id="downloadFileBtn" styleClass="form-inp-button" binding="#{fileDownload.downloadFileActionSrc}" value="#{labels.lbl_filedownload_download}" action="#{fileDownload.downloadFile}" title="#{labels.lbl_filedownload_download}"> </h:commandButton> </h:form> </trh:body> </trh:html> </t:panelGroup> </f:view> /** * File download bean used to stream ad hoc files to the client without * encountering <code>java.lang.IllegalStateException</code>. This still * occures even when calling * <code>FacesContext.getCurrentInstance().responseComplete()</code>. */ public class FileDownloadBean extends BaseBean { /** * Default constructor that downloads a file that has been temporarily * stored in the session. */ public FileDownloadBean() { downloadFile(); } /** * Gets the file for download and passes it to file download method that * takes an object. This method can be used in a faces page for a file * download action. * * @see FileDownloadBean#downloadFile(Object) * @return the faces action */ public final String downloadFile() { try { downloadFile(getFileForDownload()); } catch (Throwable e) { log.fatal("Unable to call file download", e); } return null; } /** * Processes file download * * @param file * @return the faces action */ @SuppressWarnings("unchecked") protected String downloadFile(Object file) { String errorMessage = null; try { if (file == null) { log.warn("File cannot be null. Ensure that the " + "session attribute with key: " + PARAM_FILE_KEY + " is set with a valid file or init object"); errorMessage = getMessageResourceString( "bean_filedownload_error_notfound", null, false); } else if (file instanceof File) { downloadFile((File) file, true); } else { log.error("Invalid file: " + file); } } catch (Throwable e) { log.error("Unable to download the file", e); errorMessage = getMessageResourceString( "bean_filedownload_error_unknown", null, false); } finally { completeFileDownload(errorMessage); } return null; } /** * Completes the file download process. If the error message is not null a * client alert will be initiated to notify the client of the error. If the * error message is null the response will be marked as complete. * * @param errorMessage */ protected final void completeFileDownload(String errorMessage) { try { if (errorMessage != null) { setDownloadErrorScript(errorMessage); setIsComplete(false); } else { responseComplete(); // renderResponse(); setIsComplete(true); } setFileDownloadValue(null); } catch (Throwable e) { log.error("Unable to complete file download", e); } } /** * Sets the client download script error text. * * @param errorMessage */ protected final void setDownloadErrorScript(String errorMessage) { try { StringBuffer err = new StringBuffer(); err.append("javascript:"); err.append("alert('"); err.append(isValid(errorMessage) ? errorMessage : "unknown"); err.append("');"); setClientScriptError(err.toString()); } catch (Throwable e) { if (log.isWarnEnabled()) log.warn("Unable to set the download error script: " + errorMessage); } } /*------- File Session Methods -------*/ /** * Sets the temporary session attribute that holds the file to be streamed * to the client. * * @see FileDownloadBean#setFileDownloadValue(Object) * @param file */ public static final void setFileForDownload(File file) { setFileDownloadValue(file); } /** * Sets the temporary session attribute that holds the report used to * generate a streamed report file for downloading. * * @see FileDownloadBean#setFileDownloadValue(Object) * @param report */ public static final void setFileForDownload( IExtendedReport<Report, String, IReportParam> report) { setFileDownloadValue(report); } /*------- Accessor Properties -------*/ /** * This is the button or link binding that inits the file download */ private ActionSource downloadFileActionSrc; /** * This is used for checking if the download process is complete */ private boolean isComplete; /** * Client script error returned when a file download error occurs */ private String clientScriptError; /*------- Accessor Methods -------*/ /** * @return the clientScriptError */ public String getClientScriptError() { if (clientScriptError == null) { clientScriptError = ""; } return clientScriptError; } /** * @param clientScriptError * the clientScriptError to set */ public void setClientScriptError(String clientScriptError) { this.clientScriptError = clientScriptError; } /** * @return the isComplete */ public boolean getIsComplete() { return isComplete; } /** * @param isComplete * the isComplete to set */ public void setIsComplete(boolean isComplete) { this.isComplete = isComplete; } /** * @return the downloadFileActionSrc */ public ActionSource getDownloadFileActionSrc() { return downloadFileActionSrc; } /** * @param downloadFileActionSrc * the downloadFileActionSrc to set */ public void setDownloadFileActionSrc(ActionSource downloadFileActionSrc) { this.downloadFileActionSrc = downloadFileActionSrc; } /*------- Constants -------*/ /** * log4j */ private static final Log log = LogFactory.getLog(FileDownloadBean.class); /** * serialVersionUID */ private static final long serialVersionUID = -5803068483496878170L; } In a "FacesWebUtil.java" I have the following methods: /*------- File Download Methods -------*/ /** * @see FacesWebUtil#downloadFile(FacesContext, File, boolean) */ public static final void downloadFile(FacesContext context, String filePath, String fileName, boolean isAttachment) throws NullPointerException, UnsupportedEncodingException, FileNotFoundException, IOException { if (log.isDebugEnabled()) log.debug("downloadFile(" + context + ',' + filePath + ',' + fileName + ',' + isAttachment + ')'); downloadFile(context, new File(filePath, fileName), isAttachment); } /** * @see FacesWebUtil#downloadFile(FacesContext, BufferedInputStream, String, * boolean) */ public static final void downloadFile(FacesContext context, File file, boolean isAttachment) throws UnsupportedEncodingException, IOException, FileNotFoundException { if (log.isDebugEnabled()) log.debug("downloadFile(" + context + ',' + file + ',' + isAttachment + ')'); downloadFile(context, new BufferedInputStream(new FileInputStream(file)), file .getName(), isAttachment); } /** * Streams a binary input stream to the faces response * * @param context * @param input * @param isAttachment * @param fileName */ public static final void downloadFile(FacesContext context, BufferedInputStream input, String fileName, boolean isAttachment) throws UnsupportedEncodingException, IOException { if (log.isDebugEnabled()) log.debug("downloadFile(" + context + ',' + input + ',' + fileName + ',' + isAttachment + ')'); if (input != null) { BufferedOutputStream output = null; try { if (context == null) { context = FacesContext.getCurrentInstance(); } String disposition = isAttachment ? "attachment" : "inline"; int contentLength = input.available(); // Init servlet response HttpServletResponse response = (HttpServletResponse) context .getExternalContext().getResponse(); response.setContentType("application/octet-stream"); response.setContentLength(contentLength); response.setHeader("Content-disposition", disposition + "; filename=\"" + fileName + "\""); // Write file contents to the response output = new BufferedOutputStream(response.getOutputStream()); while (contentLength-- > 0) { output.write(input.read()); } output.flush(); context.responseComplete(); // context.renderResponse(); } catch (UnsupportedEncodingException e) { log.error("Invalid file download encoding"); throw e; } catch (IOException e) { log.error("File download i/o exception"); throw e; } finally { try { if (input != null) { input.close(); } if (output != null) { output.close(); } } catch (Throwable e) { } } } else { log.error("Input stream cannot be null"); } } -----Original Message----- From: Jochen Traunecker [mailto:[EMAIL PROTECTED] Sent: Tuesday, March 27, 2007 4:27 AM To: adffaces-user@incubator.apache.org Subject: Providing Files / Streams as download-link with trinidad? Hello everybody, I'm just wondering if there is some Trinidad-specific / Faces-specific way to serve binary downloads, like PDFs stored in a database. Or do I have to provide some link to a non managed servlet? Thanks, Jochen ___________________________________________________________ Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de