cdi bean 中的资源注入

Posted

技术标签:

【中文标题】cdi bean 中的资源注入【英文标题】:resource injection in cdi bean 【发布时间】:2014-04-23 04:10:28 【问题描述】:

我不确定这是否应该工作,但我正在尝试使用带有 wildfly 的 cdi 编写一个 JMS 生产者,并坚持将资源注入 cdi 托管 bean:

public class CdiProducer 
    @Resource(name = "java:jboss/DefaultJMSConnectionFactory")
    @Produces
    QueueConnectionFactory qcf;

    @Resource(name = "java:/queue/HELLOWORLDMDBQueue")
    @Produces
    @Hello
    Queue helloWordQueue;

运行此程序我收到以下错误:

JBAS016076:将资源注入 CDI 托管 bean 时出错。找不到名为...的资源。

然而非常奇怪的是,当我将资源复制并粘贴到企业 bean 中时,一切正常!

@Stateless
public class QueueSender 
    @Resource(name="java:jboss/DefaultJMSConnectionFactory")
    QueueConnectionFactory qcf;

    @Resource(name="java:/queue/HELLOWORLDMDBQueue")
    Queue helloWordQueue;

队列定义为:

  <jms-destinations>
     <jms-queue name="HelloWorldQueue">
        <entry name="/queue/HELLOWORLDMDBQueue"/>
        <entry name="java:jboss/exported/queue/HELLOWORLDMDBQueue"/>
     </jms-queue>
  </jms-destinations>

这应该以这种方式工作吗?还是wildfly中的错误?

【问题讨论】:

你不应该使用@Resource(mappedName="...")吗? @Rudi 为什么?资源应该能够使用本地 jndi 名称? 在您的问题中,您写了“JBAS016076:将资源注入 CDI 托管 bean 时出错。找不到名为 ... 的资源”,但是您似乎已经切断了关键部分。你能包括这个关键部分吗? QueueConnectionFactory 是否失败?此外,如果您使用的是 WildFly 8,您可以简单地注入 JMSContext 并避免很多这些默认值。 @John:两者都失败了,带有相同的错误消息,似乎与各种资源一致。至于JMSContext,我很想用,但是我们使用wildfly进行本地开发,最终产品需要部署在websphere 8.5上,只有JEE6/JMS 1.1,所以没有JMSContext :( 【参考方案1】:

我没有使用 Wildfly/JBoss 的直接经验,但我对 Glassfish 有相同的经验。在我们的例子中,我们使用@PersistenceContext 来注入EntityManager,但我相信同样的规则也适用。

Weld documentation 有一个关于统一 Java EE 资源和 CDI 的部分。它展示了如何定义生产者字段(更详细地描述 here)以将此类资源连接到 CDI,这意味着您可以在其他地方使用 @Inject

字段具有双重性,它们既可以是 Java EE 组件环境注入的目标,也可以被声明为 CDI 生产者字段。因此,他们可以定义从组件环境中基于字符串的名称到类型安全注入领域中使用的类型和限定符的组合的映射。我们将表示对 Java EE 组件环境中对象的引用的生产者字段称为资源。

...

资源声明实际上包含两条信息: 从组件环境获取资源引用所需的 JNDI 名称、EJB 链接、持久性单元名称或其他元数据,以及 我们将用于将引用注入到 bean 中的类型和限定符。

例子:

@Produces @Resource(lookup="java:global/env/jdbc/CustomerDatasource") 
@CustomerDatabase Datasource customerDatabase;

其他地方:

@Inject @CustomerDatabase Datasource customerDatabase;

虽然没有在该页面上明确说明,但我认为包含此字段的类必须是 Java EE bean,即使用 EJB 注释之一进行注释,例如 @javax.ejb.Stateless@javax.ejb.Singleton

【讨论】:

【参考方案2】:

聚会迟到了,但我遇到了同样的问题。在 CDI 托管 bean 上使用 @resource 时,JNDI 总是在前面加上“java:comp/env/”。为了解决这个问题,我在企业 bean 外部使用 @resource 时将 name 更改为 lookup

@Resource(lookup = "java:/ConnectionFactory")
private ConnectionFactory connectionFactory;

【讨论】:

以上是关于cdi bean 中的资源注入的主要内容,如果未能解决你的问题,请参考以下文章

启用 CDI 注入到由生产者方法创建的 bean

使用 CDI(上下文和依赖注入)支持 bean 而不是托管 Bean

将较短范围的 Bean 实例注入 CDI 中较大范围的 bean 实例 - 它是如何工作的?

使用 CDI/Weld 注入通用 Bean

java.lang.IllegalArgumentException:WFLYWELD0037:将持久性单元注入 CDI 托管 bean 时出错

使用 CDI 将 Logger 注入 Ejb