Java8升Java17时Hibernate报错:CDI BeanManager未就绪
问题背景
升级BAS应用至Java 17,同步将Hibernate从5.3.29.Final升级到6.5.0.Final,运行在OpenLiberty 24.0.0.4上,server.xml已启用cdi-4.0、jakartaee-10.0特性。启动时抛出错误:
[ERROR ] CWWJP0015E: org.hibernate.jpa.HibernatePersistenceProvider创建mpce持久化单元的容器EntityManager工厂时出错,具体为Error attempting to apply AttributeConverter: org.hibernate.resource.beans.container.internal.NotYetReadyException: CDI BeanManager not (yet) ready to use。
已尝试以下方案但未解决:
- 在persistence.xml中添加
<property name="hibernate.delay_cdi_access" value="true"/>延迟Hibernate访问CDI - 创建BeanManagerProvider类提供BeanManager实例,在persistence.xml中配置
<property name="hibernate.cdi.beanmanager" value="com.example.BeanManagerProvider.getBeanManager"/> - 确认Jakarta EE、CDI与Hibernate ORM 6.5.0.Final的兼容性(当前cdi v4、OpenLiberty 24.0.0.4、Jakarta EE10均兼容)
核心需求:让Hibernate在CDI BeanManager完全就绪后再执行初始化。
可行解决方案
1. 调整OpenLiberty的JPA初始化顺序
OpenLiberty中可通过配置确保JPA特性在CDI之后启动,修改server.xml:
<featureManager> <feature>cdi-4.0</feature> <feature>jakartaee-10.0</feature> <!-- 明确JPA在CDI之后加载 --> <feature>jpa-3.1</feature> </featureManager> <!-- 配置持久化单元为JTA类型,依赖容器事务管理 --> <persistenceUnit id="mpce" transactionType="JTA"> <jta-data-source>jdbc/yourDataSource</jta-data-source> <class>com.example.YourEntity</class> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> </persistenceUnit>
同时在persistence.xml中设置transaction-type="JTA",避免Hibernate提前触发初始化。
2. 强制Hibernate使用CDI扩展优先逻辑
在persistence.xml中添加以下属性,让Hibernate依赖CDI扩展处理BeanManager的延迟获取:
<property name="hibernate.cdi.extension.preferred" value="true"/>
该配置会让Hibernate放弃早期直接访问BeanManager的逻辑,转而通过CDI扩展的生命周期回调获取实例。
3. 排除Hibernate自带CDI扩展依赖(解决冲突)
检查项目依赖,若存在Hibernate自带的hibernate-cdi模块,可能与OpenLiberty内置CDI容器冲突,在Maven pom.xml中排除:
<dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>6.5.0.Final</version> <exclusions> <exclusion> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-cdi</artifactId> </exclusion> </exclusions> </dependency>
4. 自定义CDI扩展触发Hibernate初始化
创建CDI扩展类,在CDI容器完全初始化后再创建EntityManagerFactory:
package com.example; import jakarta.enterprise.event.Observes; import jakarta.enterprise.inject.spi.AfterDeploymentValidation; import jakarta.enterprise.inject.spi.BeanManager; import jakarta.persistence.EntityManagerFactory; import jakarta.persistence.Persistence; public class HibernateInitializerExtension { public void onDeploymentComplete(@Observes AfterDeploymentValidation event, BeanManager beanManager) { // CDI就绪后初始化持久化单元 EntityManagerFactory emf = Persistence.createEntityManagerFactory("mpce"); // 将EMF作为事件发布,供应用内其他组件使用 beanManager.fireEvent(emf); } }
在META-INF/services/jakarta.enterprise.inject.spi.Extension文件中注册该扩展:
com.example.HibernateInitializerExtension
同时修改persistence.xml,移除自动初始化配置,由扩展类触发创建。
验证步骤
- 重启OpenLiberty,检查日志是否不再出现
NotYetReadyException - 验证自定义AttributeConverter是否能被Hibernate正常加载
- 测试基础JPA操作(实体查询、持久化)是否正常执行
内容的提问来源于stack exchange,提问作者Anmol Ahuja

