如何将ADF MODEL异常路由到JSF页面展示而非以弹窗形式呈现
ADF Model异常路由到JSF指定区域展示实现方案
可以实现将ADF Model层抛出的异常直接展示在JSF页面指定位置,无需弹窗,具体实现步骤如下:
步骤1:自定义异常处理器拦截全局Model层异常
ADF默认会将未捕获的Model层异常以弹窗形式展示,我们需要继承DCErrorHandlerImpl重写异常处理逻辑,关闭默认弹窗并将异常消息存入上下文Scope。
import oracle.adf.model.binding.DCErrorHandlerImpl; import oracle.adf.share.ADFContext; import java.util.Map; public class CustomADFErrorHandler extends DCErrorHandlerImpl { public CustomADFErrorHandler() { // 入参为true表示跳过ADF默认的异常弹窗逻辑 super(true); } @Override public void reportException(oracle.binding.BindingContext bc, Throwable ex) { // 提取核心异常信息,过滤ADF封装的冗余堆栈前缀 String errorMsg = ex.getCause() != null ? ex.getCause().getMessage() : ex.getMessage(); // 将错误消息存入pageFlowScope,页面可直接读取 Map<String, Object> pageFlowScope = ADFContext.getCurrent().getPageFlowScope(); pageFlowScope.put("modelErrorMsg", errorMsg); // 必须调用父类方法完成绑定层异常清理逻辑 super.reportException(bc, ex); } }
注册自定义异常处理器:在项目的DataBindings.cpx文件中添加ErrorHandlerClass属性,值为自定义异常处理器的全类名:
<Application xmlns="http://xmlns.oracle.com/adfm/application" version="12.2.1.4.0" id="DataBindings" ErrorHandlerClass="com.yourcompany.projectname.CustomADFErrorHandler"> <!-- 原有配置无需修改 --> </Application>
步骤2:JSF页面添加错误展示组件
在页面指定位置添加错误展示组件,绑定pageFlowScope中的错误消息,并配置局部刷新关联主表点击事件:
<!-- 错误消息展示区域 --> <af:outputText id="modelErrorTip" value="#{pageFlowScope.modelErrorMsg}" inlineStyle="color: #FF0000; font-weight: bold; margin: 8px 0;" partialTriggers="::masterTable" <!-- 替换为你的主表组件ID --> rendered="#{not empty pageFlowScope.modelErrorMsg}"/> <!-- 主表组件示例,假设ID为masterTable --> <af:table id="masterTable" var="masterRow" value="#{bindings.MasterView.collectionModel}" rowSelection="single" selectionListener="#{bindings.MasterView.collectionModel.makeCurrent}"> <!-- 主表列配置保持不变 --> </af:table>
步骤3:prepareRowSetForQuery方法中补充异常捕获逻辑
针对你提到的在prepareRowSetForQuery中执行数据库操作的场景,建议在该方法内提前捕获异常,避免异常漏触发:
import oracle.jbo.ViewRowSetImpl; import oracle.jbo.server.ViewObjectImpl; import oracle.adf.share.ADFContext; import java.sql.SQLException; import java.util.Map; public class DetailViewImpl extends ViewObjectImpl { @Override protected void prepareRowSetForQuery(ViewRowSetImpl vrs) { Map<String, Object> pageFlowScope = ADFContext.getCurrent().getPageFlowScope(); // 每次查询前清空上一次的错误消息 pageFlowScope.put("modelErrorMsg", null); try { // 原有业务逻辑:执行Iterator、ExecuteWithParams等数据库操作 super.prepareRowSetForQuery(vrs); } catch (Exception e) { // 提取数据库异常的核心提示 String errorTip = "明细数据查询失败:"; if (e.getCause() instanceof SQLException) { errorTip += ((SQLException) e.getCause()).getMessage(); } else { errorTip += e.getMessage(); } // 存入错误消息到Scope pageFlowScope.put("modelErrorMsg", errorTip); // 清空明细行集,避免展示旧的错误数据 vrs.executeEmptyRowSet(); } } }
注意事项
- 生产环境建议对异常消息做脱敏处理,避免暴露SQL语句、表结构等敏感信息
- 如果配置partialTriggers后错误消息未自动刷新,可以在主表的selectionListener方法中主动添加PPR刷新逻辑,指定刷新错误提示组件
- 自定义异常处理器中不要删除
super.reportException调用,否则会导致ADF绑定层状态异常
内容的提问来源于stack exchange,提问作者Ofer Adler
相关产品推荐
相关产品推荐

