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

CDI管理的bean随机发现

施喜
2023-03-14

我有一个ear项目,分为3个模块:

  • 网络模块,

我有一个类似这样的类:

public class UserServiceProviderEnterpriseImpl implements UserServiceProvider {
  @Override
  public UserService getUserService() {
    final BeanManager beanManager = CDI.current().getBeanManager();
    Bean<?> bean = beanManager.getBeans("userService").iterator().next();
    final CreationalContext<?> creationalContext = beanManager.createCreationalContext(bean);
    return (UserService) beanManager.getReference(bean, bean.getBeanClass(), creationalContext);
  }
}

此类属于实体模块。

该类的实例是在我的@Entity对象的@MempdSuperclass中的@PreUpdate钩子中创建的。这个类(和所说的钩子),看起来像这样:

@MappedSuperclass
@Access(AccessType.FIELD)
public abstract class BusinessObject<T extends Serializable> implements Cloneable {

  // [...]

  @PrePersist
  @PreUpdate
  @SuppressWarnings("unchecked")
  private void _prePersist() {

    // [...]

    final User currentUser = getUserServiceProvider().getUserService().getCurrentUser();

    // [...]
  }

  private static UserServiceProvider getUserServiceProvider() {
    try {
      return SenyuProperties.Core.getUserServiceProviderClass().newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      throw new RuntimeException("Erreur lors de l'instanciation du UserServiceProvider", e);
    }
  }

  // [...]
}

扩展此类的实体类与UserServiceProviderEnterpriseImpl类位于同一模块中。

我的问题出现在这一行:

Bean<?> bean = beanManager.getBeans("userService").iterator().next();

...它有时会抛出NoSuchElementExcION(由BeanManager#getBeans方法返回的空Set的原因),但有时不会。这个问题似乎是部署范围内的,因为我可以部署我的耳朵,这将发生在每次调用getUserService()方法时,但是在重新部署后,相同的场景可以完全正常工作(BeanManager#getBeans方法不再返回空Set)。

所以我的问题是:为什么这个代码的行为方式是这样的?我做错什么了吗?这种随机性的来源是什么?

如果这有帮助,我的托管bean如下所示(它属于web模块):

@Named("userService")
@SessionScoped
public class UserServiceEnterpriseImpl implements UserService, Serializable {
  @EJB
  private UserDAO dao;
  private User user;

  @Override
  public User getCurrentUser() {
    return user;
  }

  @PostConstruct
  private void initCurrentUser() {
    user = dao.findByUsername((String)SecurityUtils.getSubject().getPrincipal());
  }
}

我和Payara 4.1.1.162一起工作。

更新

我已经尝试过但没有成功的事情:

  • 在应用程序中使用initialize-in-order标记。xml(设置为true)并更改模块的顺序,
  • 将Payara更新为最新版本(4.1.1.163),
  • 通过命令行手动部署应用程序(我通常从IntelliJ执行此操作),
  • 删除BusinessObject#getUserServiceProvider()方法中的“static”关键字,
  • 所有这些都是在我更改getUserService()方法代码以使用此答案提供的解决方案之后发生的https://stackoverflow.com/a/40328987/7090063.

按照要求,这是我唯一的豆子。xml,位于src/main/webapp/web-INF目录下的my web模块中:

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
  <interceptors>
    <class>org.senyu.intranet.managedbean.ShiroSecuredInterceptor</class>
  </interceptors>
</beans>

这是我耳朵结构的一个总结,包括到目前为止我提到的课程:

ear
+-ejb (jar)
+-entity (jar)
| +-src
|   +-main
|     +-java
|       +-org
|         +-senyu
|           +-intranet
|             +-entity
|               +-user
|               | +-UserServiceProviderEnterpriseImpl
|               +-contrat
|                 +-Contrat // the class extending BusinessObject.
|                           // The latter reside in a dependency
|                           // (core-common-1.0.0-SNAPSHOT.jar).
|                           // The full list is right beneath.
|                           // The UserService and UserServiceProvider
|                           // interfaces also come from this jar.
+-web
  +-src
    +-main
    | +-java
    |   +-org
    |     +-senyu
    |       +-intranet
    |         +-managedbean
    |           +-UserServiceEnterpriseImpl
    |           +-ShiroSecuredInterceptor // @Interceptor class with an @AroundInvoke annotated method
    +-webapp
      +-WEB-INF
        +-beans.xml

这些是打包在war文件的WEB-INF/lib目录中的jar:

antlr-2.7.7.jar
aopalliance-repackaged-2.5.0-b05.jar
bootstrap-3.3.7-1.jar
cdi-api-1.1.jar
classmate-1.3.0.jar
commons-beanutils-1.8.3.jar
commons-codec-1.10.jar
commons-lang3-3.4.jar
commons-logging-1.2.jar
core-common-1.0.0-SNAPSHOT.jar // I developed this...
core-enterprise-1.0.0-SNAPSHOT.jar // ...and that too.
dom4j-1.6.1.jar
el-api-2.2.jar
geronimo-jta_1.1_spec-1.1.1.jar
gson-2.7.jar
hibernate-commons-annotations-5.0.1.Final.jar
hibernate-core-5.2.3.Final.jar
hibernate-jpa-2.1-api-1.0.0.Final.jar
hk2-api-2.5.0-b05.jar
hk2-locator-2.5.0-b05.jar
hk2-utils-2.5.0-b05.jar
jackson-annotations-2.8.0.jar
jackson-core-2.8.3.jar
jackson-databind-2.8.3.jar
jandex-2.0.0.Final.jar
javassist-3.20.0-GA.jar
javax.annotation-api-1.2.jar
javax.inject-1.jar
javax.inject-2.5.0-b05.jar
javax.ws.rs-api-2.0.1.jar
jboss-interceptors-api_1.1_spec-1.0.0.Beta1.jar
jboss-logging-3.3.0.Final.jar
jersey-client-2.23.2.jar
jersey-common-2.23.2.jar
jersey-guava-2.23.2.jar
jersey-media-jaxb-2.23.2.jar
jersey-mvc-2.23.2.jar
jersey-server-2.23.2.jar
jquery-1.12.4.jar
jsr250-api-1.0.jar
log4j-api-2.6.2.jar
log4j-core-2.6.2.jar
osgi-resource-locator-1.0.1.jar
primefaces-6.0.jar
servlet-api-2.4.jar
shiro-core-1.3.0.jar
shiro-web-1.3.0.jar
slf4j-api-1.6.4.jar
validation-api-1.1.0.Final.jar

更新2

我为org创建了一个记录器。焊接巴亚拉的jboss。以下是我在工作时得到的信息:

Sending PAT using the default event resolver: [BackedAnnotatedType] public @Named @SessionScoped class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-001536: Found [] constructors annotated with @Inject for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000002: Exactly one constructor ([EnhancedAnnotatedConstructorImpl] public org.senyu.intranet.managedbean.UserServiceEnterpriseImpl()) defined, using it as the bean constructor for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000004: Exactly one post construct method ([EnhancedAnnotatedMethodImpl] @PostConstruct private org.senyu.intranet.managedbean.UserServiceEnterpriseImpl.initCurrentUser()) for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-001536: Found [] constructors annotated with @Inject for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000002: Exactly one constructor ([EnhancedAnnotatedConstructorImpl] public org.senyu.intranet.managedbean.UserServiceEnterpriseImpl()) defined, using it as the bean constructor for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000012: Building bean metadata for class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000010: Using qualifiers [@javax.enterprise.inject.Default(), @javax.inject.Named(value=userService), @javax.enterprise.inject.Any()] for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000014: Using name userService for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000016: Using scope interface javax.enterprise.context.SessionScoped for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000106: Bean: Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-001538: Created context instance for bean Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any] identified as WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false]]
WELD-001542: Retrieving/generating proxy class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl$Proxy$_$$_WeldClientProxy]]
WELD-001541: Adding method to proxy: public org.senyu.core.common.user.User org.senyu.intranet.managedbean.UserServiceEnterpriseImpl.getCurrentUser()]]
WELD-001541: Adding method to proxy: private void org.senyu.intranet.managedbean.UserServiceEnterpriseImpl.initCurrentUser()]]
WELD-001543: Created Proxy class of type class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl$Proxy$_$$_WeldClientProxy supporting interfaces [interface org.senyu.core.common.user.UserService, interface java.io.Serializable, interface org.jboss.weld.interceptor.proxy.LifecycleMixin, interface org.jboss.weld.interceptor.util.proxy.TargetInstanceProxy, interface org.jboss.weld.bean.proxy.ProxyObject]]]
WELD-001506: Created new client proxy of type class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl$Proxy$_$$_WeldClientProxy for bean Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any] with ID WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false]]
WELD-001507: Located client proxy of type class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl$Proxy$_$$_WeldClientProxy for bean Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000200: Looked for WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false and got null in org.jboss.weld.context.beanstore.http.LazySessionBeanStore@3feb0ef2]]
WELD-000200: Looked for WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false and got null in org.jboss.weld.context.beanstore.http.LazySessionBeanStore@3feb0ef2]]
WELD-000200: Looked for WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false and got null in org.jboss.weld.context.beanstore.http.LazySessionBeanStore@3feb0ef2]]
WELD-000200: Looked for WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false and got null in org.jboss.weld.context.beanstore.http.LazySessionBeanStore@3feb0ef2]]
WELD-000220: Added WELD_S#WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false to session 0fcfe5dc9c8fb5d583f9b90ce7ae]]
WELD-000202: Added ForwardingBean userService for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any] with key WELD%ManagedBean%intranet-ear|intranet-web-1.0.0-SNAPSHOT.war|org.senyu.intranet.managedbean.UserServiceEnterpriseImpl|null|false to org.jboss.weld.context.beanstore.http.LazySessionBeanStore@3feb0ef2]]

如果没有:

Sending PAT using the default event resolver: [BackedAnnotatedType] public @Named @SessionScoped class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-001536: Found [] constructors annotated with @Inject for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000002: Exactly one constructor ([EnhancedAnnotatedConstructorImpl] public org.senyu.intranet.managedbean.UserServiceEnterpriseImpl()) defined, using it as the bean constructor for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000004: Exactly one post construct method ([EnhancedAnnotatedMethodImpl] @PostConstruct private org.senyu.intranet.managedbean.UserServiceEnterpriseImpl.initCurrentUser()) for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-001536: Found [] constructors annotated with @Inject for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000002: Exactly one constructor ([EnhancedAnnotatedConstructorImpl] public org.senyu.intranet.managedbean.UserServiceEnterpriseImpl()) defined, using it as the bean constructor for [EnhancedAnnotatedTypeImpl] public @SessionScoped @Named class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000012: Building bean metadata for class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl]]
WELD-000010: Using qualifiers [@javax.enterprise.inject.Default(), @javax.inject.Named(value=userService), @javax.enterprise.inject.Any()] for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000014: Using name userService for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000016: Using scope interface javax.enterprise.context.SessionScoped for Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
WELD-000106: Bean: Managed Bean [class org.senyu.intranet.managedbean.UserServiceEnterpriseImpl] with qualifiers [@Default @Named @Any]]]
  HHH000346: Error during managed flush [WELD-001308: Unable to resolve any beans for Type: interface org.senyu.core.common.user.UserService; Qualifiers: [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]]]]
org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308: Unable to resolve any beans for Type: interface org.senyu.core.common.user.UserService; Qualifiers: [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]
    at org.senyu.intranet.entity.user.UserServiceProviderEnterpriseImpl.getUserService(UserServiceProviderEnterpriseImpl.java:17)
Caused by: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308: Unable to resolve any beans for Type: interface org.senyu.core.common.user.UserService; Qualifiers: [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]
    at org.senyu.intranet.entity.user.UserServiceProviderEnterpriseImpl.getUserService(UserServiceProviderEnterpriseImpl.java:17)
Caused by: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308: Unable to resolve any beans for Type: interface org.senyu.core.common.user.UserService; Qualifiers: [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]
    at org.senyu.intranet.entity.user.UserServiceProviderEnterpriseImpl.getUserService(UserServiceProviderEnterpriseImpl.java:17)
Caused by: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308: Unable to resolve any beans for Type: interface org.senyu.core.common.user.UserService; Qualifiers: [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]
    at org.senyu.intranet.entity.user.UserServiceProviderEnterpriseImpl.getUserService(UserServiceProviderEnterpriseImpl.java:17)

共有1个答案

令狐高洁
2023-03-14

使用迭代器查找bean是不正确的。集合可能为空,这意味着该类型的bean还不存在。

既然你已经在使用CDI 1.1 API,最好使用CDI.当前(). Select(UserService.class). get()

 类似资料:
  • 我正计划将一个web应用程序从使用JSF托管bean转换为使用CDI托管bean。我知道我需要做以下工作: 在WEB-INF中添加空beans.xml文件。 将所有JSF@ManagedBean替换为CDI@Named Annotations。 用CDI或OmniFaces作用域注释替换所有JSF作用域注释。 将所有JSF@ManagedProperty替换为CDI@Inject Annotati

  • 短篇故事:我有一个CDIbean(注释来自而不是来自),称为。我想在创建HTTP会话时实际做一些事情。 因此,我很自然地假设会起作用:当构造这个bean的实例时,只调用一次。但是,根据这里的文档,他们说调用PostConstruct方法: 当托管bean被注入到组件中时,CDI会在所有注入发生后以及在调用所有初始值设定项后调用该方法。 我假设构造后方法将在每个会话中调用一次。然而,实践与文件一致。

  • 我是从多年使用spring和刚刚开始研究JEE7和CDI的时候来回答这个问题的。 在Spring世界中,您必须将粘贴在bean上才能将其转换为Spring bean,Spring将注入依赖项,但在CDI中,似乎没有的等效项。 null

  • 问题内容: Java EE7由一堆“ bean”定义组成: 托管Beans 1.0(JSR-316 / JSR-250) Java 1.0的依赖注入(JSR-330) CDI 1.1(JSR-346) JSF托管Beans 2.2(JSR-344) EJB 3.2(JSR-345) 为了摆脱头脑中的混乱,我研究了几篇“何时使用哪种bean类型”的文章。 EJB 的优点之一似乎是 它们仅支持声明式容

  • 我想从方法中检索注释(自定义编写的注释)。通常我可以通过访问 但是如果bean由CDI容器管理(我使用的是OpenWebBeans),那么类在运行时会得到增强。然后我必须使用超类来请求注释。目前,我试图通过在类名中查找“$$”来检测是否管理该类。但对我来说,这似乎是一个非常肮脏的解决方案。 有什么好方法可以从CDI管理的bean中检索注释吗? 详细地说,我的代码是这样的:我创建了一个注释“Cool

  • MyCart.java 这个MyCart Bean是每个HTTP会话实例化的名为CDI的Bean。 抽象类 问题描述 仅用于理解会话范围的CDI。我有两个JSP文件,如下所示 SetCDIBeanValue.jsp其中,我将获得命名会话CDI Bean(MyCart)的实例将It String属性的值设置为String值FROM_FIRST_JSP 因为这个会话的作用域是有限的,所以我想应该只有一