JSF/Seam. I have a page which accepts some parameters supplied by the user via a form, and then (when the user clicks a button on the page) the server generates a file and sends it in the response such that the user is prompted with a save-as dialog.
Here is the scenario that I'm having trouble with:
- If the user initially enters invalid input and then clicks the button, Seam processes the request, but stops at the Process Validations phase. My page then displays the validation error message.
- Next, if the user then enters the correct input and clicks the button, Seam calls my action handler, the file is generated and sent to the user in the response - but the validation error message is still displayed!
Initially, I tried some hacks to force the rerendering of the <h:messages/>
tag, but nothing was satisfactory. I now suspect the root cause is because Seam does not enter the Render Response phase when I place a file in the response.
Here's my button:
<h:commandButton value="#{messages.Reports_RunReportPDF}"
action="#{bean.generateReportPdf}"/>
And here's my action handler:
public String generateReportPdf() throws IOException {
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)facesContext.getExternalContext().getResponse();
ServletOutputStream servletOutputStream = response.getOutputStream();
// add this header to make browser prompt user with a save-as dialog
response.addHeader("Content-Disposition",
"attachment;filename=" + reportName + ".pdf");
response.setContentType(exportType.contentType());
try {
HashMap<String, Object> parameters = getReportParameters();
ReportContent content = createReport(parameters);
servletOutputStream.write(content.getContents());
servletOutputStream.flush();
servletOutputStream.close();
} catch (ReportingException e) {
e.printStackTrace();
return "fail";
}
return "success";
}
If I comment-out the code which adds the file (and just return "success"
, the page follows the navigation rules I have set up correctly. But with the file, the page stays exactly the same as it was before the button was pushed.
So, how can I both return a file in the response, and cause the <h:messages/>
tag to be rerendered?