在@ApplicationScoped bean 中注入实体管理器
Injecting an entitymanager in @ApplicationScoped bean
我正在将现有的 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[=12=]0(AbstractSharedContext.java:14)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext.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 想在每个请求(我理解)给我一个新的实体管理器,但这给我的应用程序作用域 beans 带来了问题。
我做错了什么?
因此,完整的答案是 EntityManager
是在运行时初始化阶段创建的,而 ValidatorFactory
(和 ConstraintValidator
s)是在静态初始化时创建的。
Quarkus bootstrap 进入静态初始化 -> 运行时初始化。
因此,在您的情况下,您无法访问在静态初始化期间使用 EntityManager 的 @Singleton
bean,因为它尚不可用。
制作你的 bean @ApplicationScoped
将创建一个代理并避免这个先有鸡还是先有蛋的问题。
您的整个申请将只有一个 BeanUsingEntityManager
。
EntityManager
有点不同,因为我们将其包装起来,您将在每笔交易中获得一个新的 EntityManager
/Session
,这是预期的 EntityManager
s/Session
s 不是线程安全的。
我正在将现有的 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[=12=]0(AbstractSharedContext.java:14)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext.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 想在每个请求(我理解)给我一个新的实体管理器,但这给我的应用程序作用域 beans 带来了问题。
我做错了什么?
因此,完整的答案是 EntityManager
是在运行时初始化阶段创建的,而 ValidatorFactory
(和 ConstraintValidator
s)是在静态初始化时创建的。
Quarkus bootstrap 进入静态初始化 -> 运行时初始化。
因此,在您的情况下,您无法访问在静态初始化期间使用 EntityManager 的 @Singleton
bean,因为它尚不可用。
制作你的 bean @ApplicationScoped
将创建一个代理并避免这个先有鸡还是先有蛋的问题。
您的整个申请将只有一个 BeanUsingEntityManager
。
EntityManager
有点不同,因为我们将其包装起来,您将在每笔交易中获得一个新的 EntityManager
/Session
,这是预期的 EntityManager
s/Session
s 不是线程安全的。