问题
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 simplyy
, notfoo.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, whereExampleBean
is the name of the class of the referencing bean andcom.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?
回答1:
1.
Others have suggested that I need to put an <injection-target> stanza in there. Why would that be?
I agree with your interpretation that it's unnecessary. I'm most familiar with WebSphere Application Server, and its implementation also agrees with your interpretation.
2.
The EJB specification author herself also said that the should be simply y, not foo.XBean/y.
I disagree with that interpretation and agree with yours.
3.
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.
EJB 3.1 section 16.5.2.1 says:
The following rules apply to how a deployment descriptor entry may override an EJB annotation:
- The relevant deployment descriptor entry is located based on the JNDI name used with the annotation (either defaulted or provided explicitly).
来源:https://stackoverflow.com/questions/17243775/how-do-i-override-the-value-supplied-to-a-field-annotated-with-ejb