1

Suppose I have a class like this:

@Stateless
@Local({ X.class })
public class XBean implements X {
  @EJB // name() attribute should by spec default to "foo.XBean/y", but see below
  private Y y; // Y is @Local
}

And elsewhere I have:

@Stateless
@Local({ Y.class })
public class YBean implements Y {}

@Stateless
@Local({ Y.class })
public class UnwantedYBean implements Y {}

Suppose now I want (in an XML descriptor, using the minimal amount of XML) to override or explicitly specify what gets placed in the y field in XBean.

This construct (in a META-INF/ejb-jar.xml file, of course) surprisingly (to me) does not work in GlassFish 3.1.2.2:

<ejb-jar>
 <enterprise-beans>
  <session>
   <ejb-name>XBean</ejb-name>
   <ejb-local-ref>
    <ejb-ref-name>foo.XBean/y</ejb-ref-name>
    <ejb-link>YBean</ejb-link>
   </ejb-local-ref>
  </session>
 </enterprise-beans>
</ejb-jar>

I'd like to focus this question on the ejb-jar.xml snippet above, not on any container bugs or anything like that. Specifically: is the above snippet the correct and the smallest possible way to override what EJB gets injected into my XBean.y field?

Some notes:

  • Others have suggested that I need to put an <injection-target> stanza in there. Why would that be? The injection target is already specified by virtue of my using the @EJB annotation. I don't wish to override where the injection occurs, only what actually gets injected.

  • The EJB specification author herself also said that the <ejb-ref-name> should be simply y, not foo.XBean/y. This is despite the fact that the specification says (section 16.5.1.3):

The ejb-ref-name element specifies the EJB reference name: its value is the environment entry name used in the enterprise bean code [emphasis mine].

  • There is nowhere in the EJB specification that says what the default value of the name attribute is for the @EJB annotation (!), but we can infer that it is also the environment entry name.

    The spec gives an example in section 16.5.1.1:

package com.acme.example;
@Stateless public class ExampleBean implements Example {
  ...
  @EJB private ShoppingCart myCart;
  ...
}

...which is exactly equal to mine, and then says in the same section (this is as close as we'll get to discovering what the default value for @EJB's name attribute is):

The enterprise bean reference will have the name java:comp/env/com.acme.example.ExampleBean/myCart in the referencing bean’s naming context, where ExampleBean is the name of the class of the referencing bean and com.acme.example its package.

The "naming context" in that sentence is the java:comp/env/ part, so everything else is the name, so the default value of an unadorned @EJB annotation's name attribute is classname/fieldName. I don't see how this could be otherwise. This is also backed up by the table present in the GlassFish EJB FAQ.

Bottom line: what is wrong with my XML stanza cited above? Why does it not cause a proxied instance of YBean to be injected into my XBean's @EJB-annotated private Y y field?

4

1 回答 1

0

1.

其他人建议我需要在其中放置一个 <injection-target> 节。为什么会这样?

我同意你的解释,这是不必要的。我对 WebSphere Application Server 最为熟悉,它的实现也符合您的理解。

2.

EJB 规范的作者自己也说过应该只是 y,而不是 foo.XBean/y。

我不同意这种解释,也同意你的。

3.

EJB 规范中没有任何地方说明 @EJB 注释 (!) 的 name 属性的默认值是什么,但我们可以推断它也是环境条目名称。

EJB 3.1 第 16.5.2.1 节说:

以下规则适用于部署描述符条目如何覆盖 EJB 注释:

  • 相关部署描述符条目的位置基于与注释一起使用的 JNDI 名称(默认或显式提供)。
于 2013-06-26T00:37:08.813 回答