当前位置: 首页 > 知识库问答 >
问题:

在OpenLiberty上使用Hibernate Envers设置自定义修订信息

翟善
2023-03-14

我们正在将一个应用程序从JEE7迁移到JEE8。此应用程序依赖于Hibernate ORM和Hibernate Envers。在JEE7上是版本5.2.17,在JEE8上,现在两个自由党的版本都是5.4.3。我们有一个自定义修订实体,它通过实现RevisionListener添加用户信息来扩展DefaultRevisionEntity。在JEE7上,它在OpenLiberty 19.0.0.5上运行良好,而在JEE8和Hibernate 5.4.3上,我们会遇到错误。在JEE8和Hibernate 5.4.3上,现在可以在revisionlisteners上使用CDI功能。(使用Hibernate Envers手动设置修订日期)。在OpenLiberty上,当没有bean管理器准备好使用时,revisionlistener初始化以某种方式完成,如下面的堆栈跟踪所示:

Caused by: java.lang.IllegalStateException: org.hibernate.resource.beans.container.internal.NotYetReadyException: CDI BeanManager not (yet) ready to use
[INFO]  at org.hibernate.resource.beans.container.internal.JpaCompliantLifecycleStrategy$BeanImpl.initialize(JpaCompliantLifecycleStrategy.java:112)
[INFO]  at org.hibernate.resource.beans.container.internal.CdiBeanContainerExtendedAccessImpl$BeanImpl.initialize(CdiBeanContainerExtendedAccessImpl.java:113)
[INFO]  at org.hibernate.resource.beans.container.internal.CdiBeanContainerExtendedAccessImpl$BeanImpl.getBeanInstance(CdiBeanContainerExtendedAccessImpl.java:119)
[INFO]  at org.hibernate.resource.beans.internal.ManagedBeanRegistryImpl$ContainedBeanManagedBeanAdapter.getBeanInstance(ManagedBeanRegistryImpl.java:139)
[INFO]  at org.hibernate.envers.internal.revisioninfo.DefaultRevisionInfoGenerator.generate(DefaultRevisionInfoGenerator.java:77)
[INFO]  at org.hibernate.envers.internal.synchronization.AuditProcess.getCurrentRevisionData(AuditProcess.java:133)
[INFO]  at org.hibernate.envers.internal.synchronization.AuditProcess.executeInSession(AuditProcess.java:115)
[INFO]  at org.hibernate.envers.internal.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:174)
[INFO]  at org.hibernate.envers.internal.synchronization.AuditProcessManager$1.doBeforeTransactionCompletion(AuditProcessManager.java:47)
[INFO]  at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:954)
[INFO]  ... 20 more
[INFO] Caused by: org.hibernate.resource.beans.container.internal.NotYetReadyException: CDI BeanManager not (yet) ready to use
[INFO]  ... 31 more
[INFO] Caused by: java.lang.NullPointerException
[INFO]  at org.hibernate.resource.beans.container.internal.JpaCompliantLifecycleStrategy$BeanImpl.initialize(JpaCompliantLifecycleStrategy.java:109)
[INFO]  ... 29 more

我找到了这个https://discourse.hibernate.org/t/beanmanager-createinstance-being-called-before-afterbeandiscovery-event-fired/2239可能指向同一方向的对话。

实际上,这是我们在服务器中设置的功能。xml。

<featureManager>
    <feature>jaxrs-2.1</feature> 
    <feature>jsonp-1.1</feature>
    <feature>cdi-2.0</feature>
    <feature>jpaContainer-2.2</feature>
    <feature>ejbLite-3.2</feature>
    <feature>mpMetrics-1.1</feature>
    <feature>mpHealth-1.0</feature>
    <feature>mpConfig-1.3</feature>
    <feature>servlet-4.0</feature>
</featureManager>

如果你需要更多的信息,我会提供。这是一个已知的问题吗?如果您能为这个问题提供提示或解决方案,我将不胜感激。

多谢各位。

共有1个答案

喻选
2023-03-14

是的,从我从Hibernate和IBM收到的回复来看,这似乎是一个已知的问题,正如我在论坛上提到的,在非常有用的Hibernate团队的指导下,我能够为这个问题开发一个变通方法。

解决方法是实现org。冬眠搜索hcore。spi。EnvironmentSynchronizer用于控制JPA初始化何时可以安全继续,以及javax。企业注射spi。扩展以检测CDI何时准备好了BeanManager。

我在组织中注册了我的EnvironmentSynchronizer实现。冬眠服务spi。ServiceContributorinterface。在EnvironmentSynchronizer内部,WhenEnvironmentEntrady事件方法传入一个Runnable,它表示负责JPA初始化的任务。这需要推迟到CDI完成bean发现,并且BeanManager准备就绪之后。

我的CDI扩展实现等待AfterBeanDiscovery事件方法,这是允许先前延迟的JPA初始化任务成功继续的正确时间。

在我准备好解决方案后,我开始与IBM支持部门沟通,以提高对兼容性问题的认识,并查看是否可以在将来的版本中将Hibernate初始化的细粒度控制内置到WebSphereLiberty中。IBM已经表示,他们希望Hibernate与WebSphere一起开箱即用,这非常棒,因此我希望在不久的将来,我们将在WebSphereLiberty中看到对Hibernate最新版本的全面支持。

更新:我刚刚确认,不幸的是,我们对EnvironmentSynchronizer的实现并没有推迟Envers的初始化。Envers初始化在WebSphere中启动时仍然会崩溃,我们的解决方案已经就绪。

我将更新我们与IBM的案例,以包括Envers,并在Hibernate论坛的线程中添加注释,以查看是否有任何即时选项可用。

更新:这是一个我用Hibernate Envers和一个定制的RevisionListener测试过的解决方案。将此添加到持久性。xml将允许WebSphere成功启动:

<property name="hibernate.delay_cdi_access" value="true"/>

Steve Ebersole的评论:

这个选项(2)本质上告诉Hibernate延迟访问BeanManager,直到它在运行时第一次需要访问BeanManager为止。换句话说,第一次执行需要特定CDIBeanHibernate的操作时,将向BeanManager请求。这有一个严重的缺点,即如果bean不存在,您将在运行时之前不知道这一点,可以想象,在部署几个月之后。

我们可能会在短期内使用此选项,目的是在IBM WebSphere完全支持最新版本的Hibernate开箱即用后将其删除。

 类似资料:
  • 我想使用此方法启用CORS Tomcat 8(自定义过滤器)Tomcat CORS过滤器 我困惑的步骤,使自定义过滤器被称为web.xml. 如何设置. java文件?这个文件的目录在哪里(SimpleCORSFilter)?

  • 获取设备配置信息 根据业务需求获取设备 配置的各种信息。 参数说明 字段 类型 必须 备注 device RKDevice 是 设备 namespace String 是 存储空间、根据业务填写 key String 是 信息存储Key 示例代码 Swift: RokidMobileSDK.device.getServiceInfo(device: RKDevice, namespace: Str

  • 获取设备配置信息 根据业务需求获取设备 配置的各种信息。 参数说明 字段 类型 必须 备注 deviceId String 是 设备Id namespace String 是 存储空间、根据业务填写 key String 是 信息存储Key 示例代码: Kotlin val deviceId: String = "XXX" val namespace: String = "YYY" val ke

  • 我试图在我的邮件中添加自定义标题,所以每当异常发生并最终出现在死信队列中时,我都可以看到异常是什么。然而,我所有的尝试都失败了。 使用。setHeader() 在outMessage上设置标题 正在设置exchange的属性 不允许将异常设置为有效负载中的属性。 RABBITMQ字符串:

  • 我需要帮助。 我能够设置envers在我的项目与自定义修订实体。但是,现在的要求是,我需要为User表创建一个单独的修订表(因为有数百万用户,为了更好的性能,我们不想把所有的审计数据放在一个表中) 在Hibrate envers中是否可以为特定实体创建单独的修订表? 更多关于hibernate envers的信息,请查看链接: http://docs.jboss.org/envers/docs/

  • 我正在搜索和尝试它2天没有成功,请帮助。 我想筛选woocommerce订单,以便根据产品属性将其他详细信息从db添加到订单详细信息页面,但我找不到适合此任务的woocommerce操作/筛选器挂钩。这里假设变量; 如果,那么我需要将自定义数据从数据库添加到订单详细信息页面。 注意:我不想添加额外的元框,而是想更改订单明细表: 将默认产品映像替换为存储在数据库和中的映像, 在产品名称下面添加包含自