I specified a String resource in an EJB with the @Resource
annotation. The EJB is packaged within an EJB module. The ejb.jar has an ejb-jar.xml which specifies a default value for the String resource. The ejb.jar is packaged in an ear archive together with a web module.
When the ear is deployed to WebSphere, the Environment entries for EJB modules section shows three EJB entries:
EJB_fully_qualified_name/resource_name
;Unless I provide a default value for all the variants above the resource is not injected. If I add an ejb-jar.xml to the web module, WebSphere displays four entries (one simple name and one fully qualified name of the resource per module). Is this a WebSphere quirk or am I doing something wrong? I am using WebSphere 8.5.5.3 in a cluster environment.
Here is the bean:
@Singleton
@Startup
public class ConfigSingleton {
@Resource
private String serviceLookup;
}
Here is the ejb-jar.xml:
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ConfigSingleton</ejb-name>
<env-entry>
<env-entry-name>serviceLookup</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>value</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
</ejb-jar>
You have defined 2 completely different resources; either may be looked up.
Per the Java EE specifications, when you don't use the 'name' attribute of the @Resource
annotation a default name is provided for you, which is the fully qualified class name where the annotation exists followed by the JavaBeans property name (which is basically either the name of the field, or the name of the method with 'set' removed and the next character in lowercase). The javadoc for the @Resource
annotation is a little misleading as it just says the default is the field name; but does not clarify exactly what the field name is; it is in fact the class name followed by the field name, much like you would see if you printed out the java.lang.reflect.Field
that would represent it.
When combining annotations and XML, the XML overrides the annotation only when the 'name' matches. In the sample provided, the names do not match, so you actually have 2 different resources.
If you want your <env-entry>
in XML to override the @Resource
annotation, so that you can inject a value, then you either need to change your annotation to look like this:
@Resource(name="serviceLookup")
Or change the <env-entry-name>
to the fully qualified class name / serviceLookup.
Also, when the EJB module is included in a WAR modules things get a bit more complicated. Not the 'name' aspect, but where you can provide the value. In addition to providing a value in ejb-jar.xml
, WebSphere also allows you to provide a value in ibm-ejb-jar-bnd.xml
. However, when the EJB modules is in a WAR, then it may also be provided in ibm-web-bnd.xml
... since all of the resources for all of the EJBs are visible in the java:comp/env
name space for the entire WAR module. So, in the sample, you are getting two different names because of the defaults, and what appears to be two additional copies which are really just provided in case you want to override the values in ibm-web-bnd.xml
.