【问题标题】:Injecting an entitymanager in @ApplicationScoped bean在@ApplicationScoped bean 中注入实体管理器
【发布时间】:2021-01-13 11:33:06
【问题描述】:

我正在将现有的 JBOSS JEE 应用程序移植到 Quarkus。我正在使用许多需要注入的 HV 自定义验证器。

为此,我在我的库中将所有需要注入的自定义验证器定义为 bean,如下所示:

@ApplicationScoped
public class SomeValidator implements ConstraintValidator<SomeValidation, AnObject> {

    @Inject
    public BeanUsingEntityManager bean;

注意:这是通用代码,所以它也应该在 JBOSS 上工作

接下来我定义了一个 REST 服务。 REST 服务使用这样的应用程序范围的 bean。



@ApplicationScoped
public class ApplicationContext {

    @PersistenceContext( unitName = "A" )
    EntityManager em;

    @Produces
    @EnityManagerA // required qualifier to make datasource unique in JEE context (there are more)
    public EntityManager produce() {
        return em;
    }
    // NOTE: quarkus does not allow the @Produces on a field, which is allowed in JBOSS hence the method

    @Produces
    public BeanUsingEntityManager createBeanUsingEntityManager () {
        // some logic that requires the entity manager.
    }
}

现在问题被简化了,但我一直遇到错误消息。

Caused by: javax.enterprise.inject.CreationException: Synthetic bean instance for javax.persistence.EntityManager not initialized yet: javax_persistence_EntityManager_b60c51739990fc921960fc78caeb075a811a91a6
    - a synthetic bean initialized during RUNTIME_INIT must not be accessed during STATIC_INIT
    - RUNTIME_INIT build steps that require access to synthetic beans initialized during RUNTIME_INIT should consume the SyntheticBeansRuntimeInitBuildItem
    at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.create(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:167)
    at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.create(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:190)
    at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
    at io.quarkus.arc.impl.AbstractSharedContext.access$000(AbstractSharedContext.java:14)
    at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
    at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
    at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
    at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
    at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
    at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.get(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:222)
    at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.get(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:238)
    at nl.bro.gm.gmw.dispatch.resources.ApplicationContext_Bean.create(ApplicationContext_Bean.zig:131)
    ... 59 more

我是 Quarkus 的新手。所以,不确定如何处理这个问题,或者即使我做出正确的假设。我可以想象 Quarkus 想给我一个新的 entitymanager 每个请求(我理解),但这给我的应用程序范围的 bean 带来了问题。

我在这里做错了什么?

【问题讨论】:

  • 你有比你粘贴的日志行更多的信息吗?
  • 您可以尝试将@ApplicationScoped 添加到@Produces 方法中吗?
  • 嗨@GuillaumeSmet 感谢您的快速回复。这似乎有效。我需要查看更多详细信息,看看该服务是否也有效。部署似乎是固定的。但是现在发生了什么。在应用程序生命周期期间,实体管理器是否会在所有(自定义)验证器之间共享,或者实体管理器是否会在每个请求中由 CDI 代理(并且每次调用我都会获得一个新的)?
  • 注意:我也在用同一个 entitymanager 创建一个 DAO。我想调整 JBOSS 的解决方案(所以在原始代码中)那里的行为会一样吗? (例如,它是实体管理器在 -CDI- bean 上下文中的工作方式吗)?

标签: quarkus hibernate-validator


【解决方案1】:

因此,完整的答案是EntityManager 是在运行时初始化阶段创建的,而ValidatorFactory(和ConstraintValidators)是在静态初始化阶段创建的。

Quarkus 引导程序进入静态初始化 -> 运行时初始化。

因此,在您的情况下,您无法访问在静态初始化期间使用 EntityManager 的 @Singleton bean,因为它尚不可用。

使您的 bean @ApplicationScoped 将创建一个代理并避免这种先有鸡还是先有蛋的问题。

整个应用程序只有一个BeanUsingEntityManager

EntityManager 有点不同,因为我们将它包装起来,您将在每个事务中获得一个新的 EntityManager/Session,这是预期的,因为 EntityManagers/Sessions 不是线程安全的.

【讨论】:

    猜你喜欢
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多