升级PrimeFaces11.0.0时lazy属性判定异常的解决方法
PrimeFaces 11.0.0版本lazy属性自动判定异常解决方案
不需要回退至6.2旧版本,该问题属于已知小版本逻辑bug,通过以下任意一种方案都可以完全解决,按改造成本从低到高排序如下:
方案1:显式给组件配置lazy属性(优先推荐)
该异常的触发逻辑是:<p:dataTable>、<p:treeTable>、<p:tree>这类数据组件在首次渲染时,如果绑定的value属性解析为null,框架自动推断是否为懒加载模式的逻辑会直接抛出阻断异常,而非设计中的警告日志。
直接给所有涉及的组件显式添加lazy属性即可绕开自动推断逻辑,从根源避免异常:
- 实际使用懒加载模式的组件,配置
lazy="true" - 普通非懒加载组件,配置
lazy="false"
该方案改动量极小,仅需要补全组件属性,不会影响原有业务逻辑。
方案2:初始化阶段保证value绑定值不为null
如果不想调整页面组件配置,可以修改托管Bean的初始化逻辑,保证页面首次渲染时value绑定的属性不为null:
- 非懒加载场景:在属性声明或
@PostConstruct初始化方法中给绑定的集合属性赋空初始值,例如private List<BusinessObj> dataList = new ArrayList<>(); - 懒加载场景:在初始化阶段直接实例化自定义的
LazyDataModel实现类并赋值给绑定属性,不要等用户触发加载事件后再实例化
该方案同样可以避开自动推断的异常分支,不需要修改页面代码。
方案3:自定义异常处理器拦截降级(适合页面量级大、改动成本高的场景)
如果项目中涉及的页面太多,逐个修改属性或Bean逻辑成本太高,可以通过JSF原生的异常扩展机制,把该特定异常降级为警告日志不阻断请求:
- 自定义异常处理器类,拦截匹配对应异常信息后移除异常事件,仅打印日志:
public class LazyAttributeExceptionHandler extends ExceptionHandlerWrapper { private static final Logger LOGGER = Logger.getLogger(LazyAttributeExceptionHandler.class.getName()); public LazyAttributeExceptionHandler(ExceptionHandler wrapped) { super(wrapped); } @Override public void handle() throws FacesException { Iterator<ExceptionQueuedEvent> eventIterator = getUnhandledExceptionQueuedEvents().iterator(); while (eventIterator.hasNext()) { ExceptionQueuedEvent event = eventIterator.next(); ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource(); Throwable throwable = context.getException(); // 匹配目标异常 if (throwable instanceof FacesException && throwable.getMessage() != null && throwable.getMessage().contains("Unable to automatically determine the lazy attribute")) { LOGGER.warn("Failed to auto detect component lazy attribute, fallback to default configuration", throwable); eventIterator.remove(); } } getWrapped().handle(); } }
- 自定义异常处理器工厂类,用于包装注册上述处理器:
public class LazyAttributeExceptionHandlerFactory extends ExceptionHandlerFactory { public LazyAttributeExceptionHandlerFactory(ExceptionHandlerFactory wrapped) { super(wrapped); } @Override public ExceptionHandler getExceptionHandler() { return new LazyAttributeExceptionHandler(getWrapped().getExceptionHandler()); } }
- 在项目的
faces-config.xml中注册自定义工厂:
<factory> <exception-handler-factory> com.yourpackage.LazyAttributeExceptionHandlerFactory </exception-handler-factory> </factory>
关于回退版本的说明
完全不建议回退到6.2旧版本。PrimeFaces 11.0.0相比6.2版本修复了上百个安全漏洞、做了大量性能优化和组件功能迭代,回退会直接暴露在已知安全风险下,同时丧失高版本的功能支持。单就这个lazy属性判定的bug来说,上述任意一个方案的改造成本都远低于版本回退的成本,只有当升级后存在大量其他无法解决的兼容问题、整体改造成本远高于升级收益时,才需要考虑回退。
内容的提问来源于stack exchange,提问作者ConfusedUbuntist
相关产品推荐
相关产品推荐

