背景
使用 JDeveloper 11.1.2.3 创建报告下载按钮,使用fileDownloadActionListener
如下:
<af:commandButton text="Run Report" id="submitReport">
<af:fileDownloadActionListener method="#{reportBean.run}"/>
</af:commandButton>
此 JSF 页面的顶部是以下内容:
<f:view afterPhase="#{validationBean.afterPhase}" ...>
...
<af:form id="f1">
<f:event listener="#{validationBean.postValidate}" type="postValidate"/>
这个想法是验证 Bean 可以捕获任何验证问题,如下所示:
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);
}
}
}
这按预期工作。当用户按下按钮,但表单出现错误时,validationError
会话变量设置为true
. 如果表单参数有错误,这应该允许框架防止生成报告。
问题
报告 bean的validationError
run 方法使用 session 变量,如下所示:
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();
}
}
当页面出现验证错误时,facesContext.renderResponse();
代码被执行,但生成的网页是空白的。不记录任何异常。不会产生错误。
问题
避免这种情况的一种方法是使用隐藏按钮、自定义 Java 和一些 JavaScript,如下页所述:
- 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/
然而,这种机制是复杂的。如果页面可以照常呈现,我想到的解决方案将起作用。
af:fileDownloadActionListener
事件触发后如何强制呈现页面?