【问题标题】:injectionPoint.getBean() returns null if bean is an EJB bean in Java EE 7 (CDI 1.1)如果 bean 是 Java EE 7 (CDI 1.1) 中的 EJB bean,则 injectionPoint.getBean() 返回 null
【发布时间】:2016-04-11 04:08:06
【问题描述】:

我想从 producer 方法中获取 bean 以读取其属性。在某些情况下,bean 是 EJB Singleton bean。

我已简化代码以专注于问题。

我的简单限定符:

@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface InjectMe {}

简单的制作人:

@Dependent
public class SimpleProducer {

    @Produces
    @InjectMe
    public String getInjectMe(InjectionPoint ip) {
        // ip.getBean() returns null for some reason   
        return "ip=" + ip + ", bean=" + ip.getBean();
    }
}

EJB(单例):

@Singleton
@Startup
public class SimpleSingleton {

    @Inject
    @InjectMe
    private String injectMe;

    @PostConstruct
    public void init() {
        System.out.println(injectMe);
   }

}

控制台输出:

信息:ip=[BackedAnnotatedField] @Inject @InjectMe private com.test.ejb.SimpleSingleton.injectMe, bean=null

当我将 Singleton bean 更改为 CDI bean 时,一切正常(ip.getBean() 返回不为空)。即使使用Singleton bean,它也可以在Java EE 6 中使用,但在Java EE 7 中不起作用。我正在使用 Glassfish 4 应用服务器。

这种行为是否在某处指定?

【问题讨论】:

  • 听起来像玻璃鱼虫。
  • @JohnAment:不这么认为,WildFly 的行为也是如此。还不能回答这个问题,但可能的原因可能是:1)bean发现模块行为的改变(默认:annotated); 2)注入(非上下文)类字符串; 3) 除了Dependent 之外没有声明的范围
  • 如果您调用 ip.getMember().getDeclaringClass(),您将获得两种情况下的 FQCN,这也用作 InjectionPoint API 文档中的示例,我在 Deltaspike 示例中看到它作为后续调用在bean 之后是null
  • @Alexander Rühl:谢谢您的回答。不幸的是,上述方法都不起作用:我已将发现模式更改为“全部”,更改了生产者 bean 的范围、生产者方法和单例 bean。将@Singleton 更改为@Stateless,将String 类型更改为我自己的。我什至不能使用ip.getMember().getDeclaringClass(),因为在我的场景中,我将产生的值注入到一个抽象类中,并且需要从生产者方法访问基类(我需要它的注释),但ip.getMember().getDeclaringClass() 返回抽象类。你已经写过你用 WildFly 试过了。它的工作方式相同吗?
  • @A.Panzer:是的,尝试了同样的事情,但总是为空,不知道为什么。奇怪的是,它在 CDI 1.0 中的行为有所不同。可能您唯一能做的就是将 CDI 实现的源 jar 链接到您的项目,然后转到调用 getBean()gets 的位置。

标签: cdi ejb-3.1 glassfish-4 java-ee-7


【解决方案1】:

使用

injectionPoint.getMember().getDeclaringClass()

在 WildFly 10.1.0 中为我工作,我还在 Payara Server 4.1.1.162 #badassfish(内部版本 116)中快速测试了它。我还对全新的 Payara Server 4.1.1.164 #badassfish(内部版本 28)进行了测试。但是,我不得不将生产者 bean 的范围更改为 @ApplicationScoped。默认范围不起作用。就我而言,这甚至是有道理的:)

injectionPoint.getBean().getBeanClass()

该方法适用于旧的 Payara,但不适用于新的 WildFly 10.1.0.Final 和新的 Payara Server 4.1.1.164 #badassfish(内部版本 28)。

如果您查看 Payara,当前的新版本 164 包含 Weld 2.4.0.Final,而 WildFly 10.1.0Final 使用版本 2.3.5.Final。在这两个版本中,经典代码都不起作用!

结论是,在较旧的 CDI 实现 (Weld) 上,它可以工作。在一些较新的 Weld(在 Payara 161 中引入)中,行为发生了变化。不知道是不是故意的。

但是,解决方案是使用

injectionPoint.getMember().getDeclaringClass()

并用

注释生产者 bean
@javax.enterprise.context.ApplicationScoped

注释。

【讨论】:

  • 在 weblogic 12.2.1 (CDI 1.1) 上测试过,我也有同样的问题。虽然它在 weblogic 12.1.3 (CDI 1.0) 上运行良好。正如你所说,我使用injectionPoint.getMember().getDeclaringClass() 解决了这个问题
猜你喜欢
  • 2015-07-29
  • 2021-06-17
  • 2013-06-30
  • 2018-06-22
  • 2012-04-12
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
相关资源
最近更新 更多