Enterprise Bean's Environment as a JNDI Naming Context (declare dependencies on external resources)
The enterprise bean's environment is a mechanism that allows customization of the enterprise bean's business logic during deployment or assembly. The enterprise bean's environment allows the enterprise bean to be customized without the need to access or change the enterprise bean's source code.
Annotations and deployment descriptors are the main vehicles for conveying access information to the application assembler and deployer about beans' requirements for customization of business logic and access to external information.
The container implements the enterprise bean’s environment, and provides it as a JNDI naming context. The enterprise bean's environment is used as follows:
The enterprise bean makes use of entries from the environment. Entries from the environment may be injected by the container into the bean's fields or methods, or the methods of the bean may access the environment using the EJBContext lookup method or the JNDI interfaces. The Bean Provider declares in Java language metadata annotations or in the deployment descriptor all the environment entries that the enterprise bean expects to be provided in its environment at runtime.
The container provides an implementation of the JNDI naming context that stores the enterprise bean environment. The container also provides the tools that allow the Deployer to create and manage the environment of each enterprise bean.
The Deployer uses the tools provided by the container to create and initialize the environment entries that are declared by means of the enterprise bean's annotations or deployment descriptor. The Deployer can set and modify the values of the environment entries.
The container injects entries from the environment into the enterprise bean's fields or methods as specified by the bean's metadata annotations or the deployment descriptor.
The container makes the environment naming context available to the enterprise bean instances at runtime. The enterprise bean's instances can use the EJBContext lookup method or the JNDI interfaces to obtain the values of the environment entries.
Sharing of Environment Entries
Each enterprise bean defines its own set of environment entries. All instances of an enterprise bean share the same environment entries; the environment entries are not shared with other enterprise beans. Enterprise bean instances are not allowed to modify the bean's environment at runtime.
In general, lookups of objects in the JNDI java: namespace are required to return a NEW INSTANCE of the requested object every time. Exceptions are allowed for the following:
The container knows the object is immutable (for example, objects of type java.lang.String), or knows that the application can't change the state of the object.
The object is defined to be a singleton, such that only one instance of the object may exist in the JVM.
The name used for the lookup is defined to return an instance of the object that might be shared. The name java:comp/ORB is such a name.
In these cases, a shared instance of the object may be returned. In all other cases, a NEW INSTANCE of the requested object must be returned on each lookup. Note that, in the case of resource adapter connection objects, it is the resource adapter's ManagedConnectionFactory implementation that is responsible for satisfying this requirement.
Each injection of an object corresponds to a JNDI lookup. Whether a new instance of the requested object is injected, or whether a shared instance is injected, is determined by the rules described above.
Annotations for Environment Entries
A field or method of a bean class may be annotated to request that an entry from the bean's environment be injected. Any of the types of resources or other environment entries described in this chapter may be injected. Injection may also be requested using entries in the deployment descriptor corresponding to each of these resource types. The field or method MAY have any access qualifier (public, private, etc.) but MUST NOT be static.
A field of the bean class may be the target of injection. The field MUST NOT be final. By default, the name of the field is combined with the name of the class in which the annotation is used and is used directly as the name in the bean's naming context. For example, a field named myDatabase in the class MySessionBean in the package com.acme.example would correspond to the JNDI name java:comp/env/com.acme.example.MySessionBean/myDatabase. The annotation also allows the JNDI name to be specified explicitly.
Environment entries may also be injected into the bean through bean methods that follow the naming conventions for JavaBeans properties. The annotation is applied to the set method for the property, which is the method that is called to inject the environment entry. The JavaBeans property name (not the method name) is used as the default JNDI name. For example, a method named setMyDatabase in the same MySessionBean class would correspond to the JNDI name java:comp/env/com.example.MySessionBean/myDatabase.
When a deployment descriptor entry is used to specify injection, the JNDI name and the instance variable name or property name are both specified explicitly. Note that the JNDI name is ALWAYS relative to the java:comp/env naming context.
Each resource may only be injected into a SINGLE field or method of the bean. Requesting injection of the java:comp/env/com.example.MySessionBean/myDatabase resource into both the setMyDatabase method and the myDatabase instance variable is an ERROR. Note, however, that either the field or the method could request injection of a resource of a different (non-default) name. By explicitly specifying the JNDI name of a resource, a single resource may be injected into MULTIPLE fields or methods of multiple classes.
Annotations may also be applied to the bean class itself. These annotations declare an entry in the bean's environment, but do not cause the resource to be injected. Instead, the bean is expected to use the EJBContext lookup method or the methods of the JNDI API to lookup the entry. When the annotation is applied to the bean class, the JNDI name and the environment entry type MUST be explicitly specified.
Annotations may appear on the bean class, or on any superclass. A resource annotation on any class in the inheritance hierarchy defines a resource needed by the bean. However, injection of such resources follows the Java language overriding rules for the visibility of fields and methods. A method definition that overrides a method on a superclass defines the resource, if any, to be injected into that method. An overriding method may request injection of a different resource than is requested by the superclass, or it may request no injection even though the superclass method requests injection.
In addition, fields or methods that are not visible in or are hidden (as opposed to overridden) by a subclass may still request injection. This allows, for example, a private field to be the target of injection and that field to be used in the implementation of the superclass, even though the subclass has no visibility into that field and doesn't know that the implementation of the superclass is using an injected resource. Note that a declaration of a field in a subclass with the same name as a field in a superclass always causes the field in the superclass to be hidden.
Annotations and Deployment Descriptors
Environment entries may be declared by the use of annotations, without need for any deployment descriptor entries. Environment entries may also be declared by deployment descriptor entries, without need for any annotations. The same environment entry may be declared using both an annotation and a deployment descriptor entry. In this case, the information in the deployment descriptor entry may be used to override some of the information provided in the annotation. This approach may be used by an Application Assembler to override information provided by the Bean Provider. Deployment descriptor entries should not be used to request injection of a resource into a field or method that has not been designed for injection.
The following rules apply to how a deployment descriptor entry may override a Resource annotation:
The relevant deployment descriptor entry is located based on the JNDI name used with the annotation (either defaulted or provided explicitly).
The type specified in the deployment descriptor must be assignable to the type of the field or property or the type specified in the Resource annotation.
The description, if specified, overrides the description element of the annotation.
The injection target, if specified, must name exactly the annotated field or property method.
The res-sharing-scope element, if specified, overrides the shareable element of the annotation. In general, the Application Assembler or Deployer should NEVER change the value of this element, as doing so is likely to break the application.
The res-auth element, if specified, overrides the authenticationType element of the annotation. In general, the Application Assembler or Deployer should NEVER change the value of this element, as doing so is likely to break the application.
Restrictions on the overriding of environment entry values depend on the type of environment entry.
EJB References
Injection of EJB References
The Bean Provider uses the EJB annotation to annotate a field or setter property method of the bean class as a target for the injection of an EJB reference. The reference may be to a session bean's business interface or to the local home interface or remote home interface of a session bean or entity bean.
The following example illustrates how an enterprise bean uses the EJB annotation to reference another enterprise bean. 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 target of the reference must be resolved by the Deployer.
package com.acme.example; @Stateless public class ExampleBean implements Example { @EJB private ShoppingCart myCart; ... }
The following example illustrates use of all portable elements of the EJB annotation. In this case, the enterprise bean reference would have the name java:comp/env/ejb/shopping-cart in the referencing bean's naming context. This reference is linked to a bean named cart1.
@EJB( name="ejb/shopping-cart", beanInterface=ShoppingCart.class, beanName="cart1", description="The shopping cart for this application" ) private ShoppingCart myCart;
If the ShoppingCart bean were instead written to the EJB 2.1 client view, the EJB reference would be to the bean's home interface. For example:
@EJB( name="ejb/shopping-cart", beanInterface=ShoppingCartHome.class, beanName="cart1", description="The shopping cart for this application" ) private ShoppingCartHome myCartHome;
EJB Reference Programming Interfaces
The Bean Provider may use EJB references to locate the business interfaces or home interfaces of other enterprise beans as follows.
Assign an entry in the enterprise bean's environment to the reference.
The EJB specification RECOMMENDS, but does not require, that all references to other enterprise beans be organized in the ejb subcontext of the bean's environment (i.e., in the java:comp/env/ejb JNDI context). Note that enterprise bean references declared by means of annotations will not, by default, be in any subcontext.
Look up the business interface or home interface of the referenced enterprise bean in the enterprise bean's environment using the EJBContext lookup method or the JNDI API.
The following example illustrates how an enterprise bean uses an EJB reference to locate the remote home interface of another enterprise bean using the JNDI APIs:
@EJB(name="ejb/EmplRecord", beanInterface=EmployeeRecordHome.class) @Stateless public class EmployeeServiceBean implements EmployeeService { public void changePhoneNumber(...) { // Obtain the default initial JNDI context. Context initCtx = new InitialContext(); // Look up the home interface of the EmployeeRecord // enterprise bean in the environment. Object result = initCtx.lookup("java:comp/env/ejb/EmplRecord"); // Convert the result to the proper type. EmployeeRecordHome emplRecordHome = (EmployeeRecordHome) javax.rmi.PortableRemoteObject.narrow(result, EmployeeRecordHome.class); ... } }
In the example, the Bean Provider of the EmployeeServiceBean enterprise bean assigned the environment entry ejb/EmplRecord as the EJB reference name to refer to the remote home of another enterprise bean.
Declaration of EJB References in Deployment Descriptor
Although the EJB reference is an entry in the enterprise bean's environment, the Bean Provider must not use a env-entry element to declare it. Instead, the Bean Provider must declare all the EJB references using the ejb-ref and ejb-local-ref elements of the deployment descriptor. This allows the ejb-jar consumer (i.e. Application Assembler or Deployer) to discover all the EJB references used by the enterprise bean. Deployment descriptor entries may also be used to specify injection of an EJB reference into a bean.
Each ejb-ref or ejb-local-ref element describes the interface requirements that the referencing enterprise bean has for the referenced enterprise bean. The ejb-ref element is used for referencing an enterprise bean that is accessed through its remote business interface or remote home and component interfaces. The ejb-local-ref element is used for referencing an enterprise bean that is accessed through its local business interface or local home and component interfaces.
The ejb-ref element contains the description, ejb-ref-name, ejb-ref-type, home, and remote elements.
The ejb-local-ref element contains the description, ejb-ref-name, ejb-ref-type, local-home, and local elements.
The ejb-ref-name element specifies the EJB reference name: its value is the environment entry name used in the enterprise bean code. The ejb-ref-name MUST be specified. The optional ejb-ref-type element specifies the expected type of the enterprise bean: its value must be either Entity or Session. The home and remote or local-home and local elements specify the expected Java types of the referenced enterprise bean's interface(s). If the reference is to an EJB 2.1 remote client view interface, the home element is REQUIRED. Likewise, if the reference is to an EJB 2.1 local client view interface, the local-home element is REQUIRED. The remote element of the ejb-ref element refers to either the business interface type or the component interface, depending on whether the reference is to a bean's EJB 3.0 or EJB 2.1 remote client view. Likewise, the local element of the ejb-local-ref element refers to either the business interface type or the component interface, depending on whether the reference is to a bean's EJB 3.0 or EJB 2.1 local client view.
An EJB reference is scoped to the enterprise bean whose declaration contains the ejb-ref or ejb-local-ref element. This means that the EJB reference is NOT accessible to other enterprise beans at runtime, and that other enterprise beans may define ejb-ref and/or ejb-local-ref elements with the same ejb-ref-name WITHOUT causing a name conflict.
The following example illustrates the declaration of EJB references in the deployment descriptor:
<enterprise-beans> <session> <ejb-name>EmployeeService</ejb-name> <ejb-class>com.wombat.empl.EmployeeServiceBean</ejb-class> ... <ejb-ref> <description> This is a reference to an EJB 2.1 entity bean that encapsulates access to employee records. </description> <ejb-ref-name>ejb/EmplRecord</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <home>com.wombat.empl.EmployeeRecordHome</home> <remote>com.wombat.empl.EmployeeRecord</remote> </ejb-ref> <ejb-local-ref> <description> This is a reference to the local business interface of an EJB 3.0 session bean that provides a payroll service. </description> <ejb-ref-name>ejb/Payroll</ejb-ref-name> <local>com.aardvark.payroll.Payroll</local> </ejb-local-ref> <ejb-local-ref> <description> This is a reference to the local business interface of an EJB 3.0 session bean that provides a pension plan service. </description> <ejb-ref-name>ejb/PensionPlan</ejb-ref-name> <local>com.wombat.empl.PensionPlan</local> </ejb-local-ref> </session> </enterprise-beans>
The Application Assembler can use the ejb-link element in the deployment descriptor to link an EJB reference to a target enterprise bean.
The Application Assembler specifies the link between two enterprise beans as follows:
The Application Assembler uses the optional ejb-link element of the ejb-ref or ejb-local-ref element of the referencing enterprise bean. The value of the ejb-link element is the name of the target enterprise bean. (This is the bean name as defined by metadata annotation (or default) in the bean class or in the ejb-name element of the target enterprise bean.) The target enterprise bean can be in any ejb-jar file in the same Java EE application as the referencing application component.
Alternatively, to avoid the need to rename enterprise beans to have unique names within an entire Java EE application, the Application Assembler may use the following syntax in the ejb-link element of the referencing application component. The Application Assembler specifies the path name of the ejb-jar file containing the referenced enterprise bean and appends the ejb-name of the target bean separated from the path name by # . The path name is relative to the referencing application component jar file. In this manner, multiple beans with the same ejb-name may be uniquely identified when the Application Assembler cannot change ejb-names.
The Application Assembler must ensure that the target enterprise bean is type-compatible with the declared EJB reference. This means that the target enterprise bean must be of the type indicated in the ejb-ref-type element, if present, and that the business interface or home and component interfaces of the target enterprise bean must be Java type-compatible with the interfaces declared in the EJB reference.
The following illustrates an ejb-link in the deployment descriptor:
<enterprise-beans> <session> <ejb-name>EmployeeService</ejb-name> <ejb-class>com.wombat.empl.EmployeeServiceBean</ejb-class> ... <ejb-ref> <ejb-ref-name>ejb/EmplRecord</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <home>com.wombat.empl.EmployeeRecordHome</home> <remote>com.wombat.empl.EmployeeRecord</remote> <ejb-link>EmployeeRecord</ejb-link> </ejb-ref> ... </session> ... <entity> <ejb-name>EmployeeRecord</ejb-name> <home>com.wombat.empl.EmployeeRecordHome</home> <remote>com.wombat.empl.EmployeeRecord</remote> ... </entity> ... </enterprise-beans>
The Application Assembler uses the ejb-link element to indicate that the EJB reference EmplRecord declared in the EmployeeService enterprise bean has been linked to the EmployeeRecord enterprise bean.
The following example illustrates using the ejb-link element to indicate an enterprise bean reference to the ProductEJB enterprise bean that is in the same Java EE application unit but in a DIFFERENT ejb-jar file:
<entity> ... <ejb-name>OrderEJB</ejb-name> <ejb-class>com.wombat.orders.OrderBean</ejb-class> ... <ejb-ref> <ejb-ref-name>ejb/Product</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <home>com.acme.orders.ProductHome</home> <remote>com.acme.orders.Product</remote> <ejb-link>../products/product.jar#ProductEJB</ejb-link> </ejb-ref> ... </entity>
The following example illustrates using the ejb-link element to indicate an enterprise bean reference to the ShoppingCart enterprise bean that is in the same Java EE application unit but in a DIFFERENT ejb-jar file. The reference was originally declared in the bean's code using an annotation. The Application Assembler provides ONLY the link to the bean:
... <ejb-ref> <ejb-ref-name>ShoppingService/myCart</ejb-ref-name> <ejb-link>../products/product.jar#ShoppingCart</ejb-link> </ejb-ref>
Resource Manager Connection Factory References
A resource manager connection factory is an object that is used to create connections to a resource manager. For example, an object that implements the javax.sql.DataSource interface is a resource manager connection factory for java.sql.Connection objects that implement connections to a database management system.
A field or a method of an enterprise bean may be annotated with the Resource annotation. The authenticationType and shareable elements of the Resource annotation may be used to control the type of authentication desired for the resource and the shareability of connections acquired from the factory.
The following code example illustrates how an enterprise bean uses annotations to declare resource manager connection factory references.
//The employee database. @Resource javax.sql.DataSource employeeAppDB; ... public void changePhoneNumber(...) { ... // Invoke factory to obtain a resource. The security // principal for the resource is not given, and // therefore it will be configured by the Deployer. java.sql.Connection con = employeeAppDB.getConnection(); ... }
The Bean Provider must use resource manager connection factory references to obtain connections to resources as follows.
Assign an entry in the enterprise bean's environment to the resource manager connection factory reference.
The EJB specification recommends, but does NOT require, that all resource manager connection factory references be organized in the subcontexts of the bean's environment, using a different subcontext for each resource manager type. For example, all JDBC DataSource references might be declared in the java:comp/env/jdbc subcontext, and all JMS connection factories in the java:comp/env/jms subcontext. Also, all JavaMail connection factories might be declared in the java:comp/env/mail subcontext and all URL connection factories in the java:comp/env/url subcontext. Note that resource manager connection factory references declared via annotations will NOT, by default, appear in any subcontext.
Lookup the resource manager connection factory object in the enterprise bean's environment using the EJBContext lookup method or using the JNDI API.
Invoke the appropriate method on the resource manager connection factory to obtain a connection to the resource. The factory method is specific to the resource type. It is possible to obtain multiple connections by calling the factory object multiple times.
The Bean Provider can control the shareability of the connections acquired from the resource manager connection factory. By default, connections to a resource manager are shareable across other enterprise beans in the application that use the same resource in the same transaction context. The Bean Provider can specify that connections obtained from a resource manager connection factory reference are not shareable by specifying the value of the shareable annotation element to false or the res-sharing-scope deployment descriptor element to be Unshareable. The sharing of connections to a resource manager allows the container to optimize the use of connections and enables the container's use of local transaction optimizations.
The Bean Provider has two choices with respect to dealing with associating a principal with the resource manager access:
Allow the Deployer to set up principal mapping or resource manager sign-on information. In this case, the enterprise bean code invokes a resource manager connection factory method that has no security-related parameters.
Sign on to the resource manager from the bean code. In this case, the enterprise bean invokes the appropriate resource manager connection factory method that takes the sign-on information as method parameters.
The Bean Provider uses the authenticationType annotation element or the res-auth deployment descriptor element to indicate which of the two resource manager authentication approaches is used.
The following code sample illustrates obtaining a JDBC connection when the EJBContext lookup method is used:
@Resource(name="jdbc/EmployeeAppDB", type=javax.sql.DataSource) @Stateless public class EmployeeServiceBean implements EmployeeService { @Resource SessionContext ctx; public void changePhoneNumber(...) { ... // use context lookup to obtain resource manager // connection factory javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("jdbc/EmployeeAppDB"); // Invoke factory to obtain a connection. The security // principal is not given, and therefore // it will be configured by the Deployer. java.sql.Connection con = ds.getConnection(); ... } }
The following code sample illustrates obtaining a JDBC connection when the JNDI APIs are used directly:
@Resource(name="jdbc/EmployeeAppDB", type=javax.sql.DataSource) @Stateless public class EmployeeServiceBean implements EmployeeService { EJBContext ejbContext; public void changePhoneNumber(...) { ... // obtain the initial JNDI context Context initCtx = new InitialContext(); // perform JNDI lookup to obtain resource manager // connection factory javax.sql.DataSource ds = (javax.sql.DataSource) initCtx.lookup("java:comp/env/jdbc/EmployeeAppDB"); // Invoke factory to obtain a connection. The security // principal is not given, and therefore // it will be configured by the Deployer. java.sql.Connection con = ds.getConnection(); ... } }
Although a resource manager connection factory reference is an entry in the enterprise bean's environment, the Bean Provider must not use an env-entry element to declare it.
Instead, if metadata annotations are not used, the Bean Provider must declare all the resource manager connection factory references in the deployment descriptor using the resource-ref elements. This allows the ejb-jar consumer (i.e. Application Assembler or Deployer) to discover all the resource manager connection factory references used by an enterprise bean. Deployment descriptor entries may also be used to specify injection of a resource manager connection factor reference into a bean.
Each resource-ref element describes a single resource manager connection factory reference. The resource-ref element consists of the description element; the mandatory res-ref-name element; and the optional res-type, res-auth and res-sharing-scope elements. The res-ref-name element contains the name of the environment entry used in the enterprise bean's code. The name of the environment entry is RELATIVE to the java:comp/env context (e.g., the name should be jdbc/EmployeeAppDB rather than java:comp/env/jdbc/EmployeeAppDB). The res-type element contains the Java type of the resource manager connection factory that the enterprise bean code expects. The res-type element is optional if an injection target is specified for the resource; in this case, the res-type defaults to the type of the injection target. The res-auth element indicates whether the enterprise bean code performs resource manager sign-on programmatically, or whether the container signs on to the resource manager using the principal mapping information supplied by the Deployer. The Bean Provider indicates the sign-on responsibility by setting the value of the res-auth element to Application or Container. If the res-auth element is not specified, Container sign-on is ASSUMED. The res-sharing-scope element indicates whether connections to the resource manager obtained through the given resource manager connection factory reference are to be shared or whether connections are unshareable. The value of the res-sharing-scope element is Shareable or Unshareable. If the res-sharing-scope element is not specified, connections are assumed to be SHAREABLE.
A resource manager connection factory reference is scoped to the enterprise bean whose declaration contains the resource-ref element. This means that the resource manager connection factory reference is not accessible from other enterprise beans at runtime, and that other enterprise beans may define resource-ref elements with the same res-ref-name without causing a name conflict.
The following example is the declaration of resource manager connection factory references used by the EmployeeService enterprise bean illustrated in the previous subsection:
<enterprise-beans> <session> <ejb-name>EmployeeService</ejb-name> <ejb-class>com.wombat.empl.EmployeeServiceBean</ejb-class> ... <resource-ref> <description> A data source for the database in which the EmployeeService enterprise bean will record a log of all transactions. </description> <res-ref-name>jdbc/EmployeeAppDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Shareable</res-sharing-scope> </resource-ref> ... </session> </enterprise-beans>
The following example illustrates the declaration of JMS resource manager connection factory references:
<enterprise-beans> <session> ... <resource-ref> <description> A queue connection factory used by the MySession enterprise bean to send notifications. </description> <res-ref-name>jms/qConnFactory</res-ref-name> <res-type>javax.jms.QueueConnectionFactory</res-type> <res-auth>Container</res-auth> <res-sharing-scope>Unshareable</res-sharing-scope> </resource-ref> ... </session> </enterprise-beans>
Resource Environment References
Resource environment references are special entries in the enterprise bean's environment. The Deployer binds the resource environment references to administered objects in the target operational environment.
A field or a method of a bean may be annotated with the Resource annotation to request injection of a resource environment reference. The authenticationType and shareable elements of the Resource annotation MUST NOT be specified; resource environment entries are NOT shareable and DO NOT require authentication. The use of the Resource annotation to declare a resource environment reference differs from the use of the Resource annotation to declare simple environment references only in that the type of a resource environment reference is not one of the Java language types used for simple environment references.
The Bean Provider must use resource environment references to locate administered objects that are associated with resources, as follows.
Assign an entry in the enterprise bean's environment to the reference.
The EJB specification recommends, but does not require, that all resource environment references be organized in the appropriate subcontext of the bean's environment for the resource type. Note that the resource environment references declared via annotations will not, by default, appear in any subcontext.
Look up the administered object in the enterprise bean’s environment using the EJBContext lookup method or the JNDI API.
Although the resource environment reference is an entry in the enterprise bean's environment, the Bean Provider MUST NOT use a env-entry element to declare it. Instead, the Bean Provider must declare all references to administered objects associated with resources using either annotations in the bean's source code or the resource-env-ref elements of the deployment descriptor. This allows the ejb-jar consumer to discover all the resource environment references used by the enterprise bean. Deployment descriptor entries may also be used to specify injection of a resource environment reference into a bean.
Each resource-env-ref element describes the requirements that the referencing enterprise bean has for the referenced administered object. The resource-env-ref element contains optional description and resource-env-ref-type elements, and the MANDATORY resource-env-ref-name element. The resource-env-ref-type element is optional if an injection target is specified for the resource environment reference; in this case the resource-env-ref-type defaults to the type of the injection target.
The resource-env-ref-name element specifies the resource environment reference name: its value is the environment entry name used in the enterprise bean CODE. The name of the environment entry is relative to the java:comp/env context. The resource-env-ref-type element specifies the expected type of the referenced object.
A resource environment reference is scoped to the enterprise bean whose declaration contains the resource-env-ref element. This means that the resource environment reference is NOT accessible to other enterprise beans at runtime, and that other enterprise beans MAY define resource-env-ref elements with the SAME resource-env-ref-name without causing a name conflict.
Persistence Context References
Persistence context references are special entries in the enterprise bean's environment. The Deployer binds the persistence context references to container-managed entity managers for persistence contexts of the specified type and configured in accordance with their persistence unit.
A field or a method of an enterprise bean may be annotated with the PersistenceContext annotation. The name element specifies the name under which a container-managed entity manager for the referenced persistence unit may be located in the JNDI naming context. The OPTIONAL unitName element specifies the name of the persistence unit as declared in the persistence.xml file that defines the persistence unit. The OPTIONAL type element specifies whether a transaction-scoped or extended persistence context is to be used. If the type is not specified, a transaction-scoped persistence context will be used. References to container-managed entity managers with extended persistence contexts can ONLY be injected into stateful session beans. The OPTIONAL properties element specifies configuration properties to be passed to the persistence provider when the entity manager is created.
The following code example illustrates how an enterprise bean uses annotations to declare persistence context references:
@PersistenceContext(type=EXTENDED) EntityManager em;
The Bean Provider must use persistence context references to obtain references to a container-managed entity manager configured for a persistence unit as follows:
Assign an entry in the enterprise bean's environment to the persistence context reference.
The EJB specification recommends, but does not require, that all persistence context references be organized in the java:comp/env/persistence subcontexts of the bean's environment.
Lookup the container-managed entity manager for the persistence unit in the enterprise bean's environment using the EJBContext lookup method or using the JNDI API.
The following code sample illustrates obtaining an entity manager for a persistence context when the EJBContext lookup method is used:
@PersistenceContext(name="persistence/InventoryAppMgr") @Stateless public class InventoryManagerBean implements InventoryManager { @Resource SessionContext ctx; public void updateInventory(...) { ... // use context lookup to obtain container-managed entity // manager EntityManager em =(EntityManager) ctx.lookup("persistence/InventoryAppMgr"); ... } }
The following code sample illustrates obtaining an entity manager when the JNDI APIs are used directly:
@PersistenceContext(name="persistence/InventoryAppMgr") @Stateless public class InventoryManagerBean implements InventoryManager { EJBContext ejbContext; public void updateInventory(...) { ... // obtain the initial JNDI context Context initCtx = new InitialContext(); // perform JNDI lookup to obtain container-managed entity // manager EntityManager em = (EntityManager) initCtx.lookup("java:comp/env/persistence/InventoryAppMgr"); ... } }
Although a persistence context reference is an entry in the enterprise bean's environment, the Bean Provider must not use an env-entry element to declare it.
Instead, if metadata annotations are not used, the Bean Provider MUST declare all the persistence context references in the deployment descriptor using the persistence-context-ref elements. This allows the ejb-jar consumer (i.e. Application Assembler or Deployer) to discover all the persistence context references used by an enterprise bean. Deployment descriptor entries may also be used to specify injection of a persistence context reference into a bean.
Each persistence-context-ref element describes a single container-managed entity manager reference. The persistence-context-ref element consists of the OPTIONAL description, persistence-unit-name, persistence-context-type and persistence-property elements, and the MANDATORY persistence-context-ref-name element.
The persistence-context-ref-name element contains the name of the environment entry used in the enterprise bean's CODE. The name of the environment entry is relative to the java:comp/env context (e.g., the name should be persistence/InventoryAppMgr rather than java:comp/env/persistence/InventoryAppMgr). The persistence-unit-name element is the name of the persistence unit, as specified in the persistence.xml file for the persistence unit. The persistence-context-type element specifies whether a transaction-scoped or extended persistence context is to be used. Its value is either Transaction or Extended. If the persistence context type is not specified, a transaction-scoped persistence context will be used. The optional persistence-property elements specify configuration properties that are passed to the persistence provider when the entity manager is created.
The following example is the declaration of a persistence context reference used by the InventoryManagerBean enterprise bean illustrated in the previous subsection:
<enterprise-beans> <session> <ejb-name>InventoryManagerBean</ejb-name> <ejb-class>com.wombat.empl.InventoryManagerBean</ejb-class> ... <persistence-context-ref> <description> Persistence context for the inventory management application. </description> <persistence-context-ref-name> persistence/InventoryAppMgr </persistence-context-ref-name> <persistence-unit-name> InventoryManagement </persistence-unit-name> </persistence-context-ref> </session> </enterprise-beans>
The Application Assembler can use the persistence-unit-name element in the deployment descriptor to specify a reference to a persistence unit. In this manner, multiple persistence units with the same persistence unit name may be uniquely identified when persistence unit names cannot be changed.
For example:
<enterprise-beans> <session> <ejb-name>InventoryManagerBean</ejb-name> <ejb-class>com.wombat.empl.InventoryManagerBean</ejb-class> ... <persistence-context-ref> <description> Persistence context for the inventory management application. </description> <persistence-context-ref-name> persistence/InventoryAppMgr </persistence-context-ref-name> <persistence-unit-name> ../lib/inventory.jar#InventoryManagement </persistence-unit-name> </persistence-context-ref> </session> </enterprise-beans>
The Application Assembler uses the persistence-unit-name element to link the persistence unit name InventoryManagement declared in the InventoryManagerBean to the persistence unit named InventoryManagement defined in inventory.jar.
The following rules apply to how a deployment descriptor entry may override a PersistenceContext annotation:
The relevant deployment descriptor entry is located based on the JNDI name used with the annotation (either defaulted or provided explicitly).
The persistence-unit-name OVERRIDES the unitName element of the annotation. The Application Assembler or Deployer should exercise CAUTION in changing this value, if specified, as doing so is likely to break the application.
The persistence-context-type, if specified, OVERRIDES the type element of the annotation. In general, the Application Assembler or Deployer SHOULD NEVER change the value of this element, as doing so is likely to break the application.
Any persistence-property elements are added to those specified by the PersistenceContext annotation. If the name of a specified property is the same as one specified by the PersistenceContext annotation, the value specified in the annotation IS OVERRIDEN.
The injection target, if specified, must name exactly the annotated field or property method.
Persistence Unit References
Persistence unit references are special entries in the enterprise bean's environment. The Deployer binds the persistence unit references to entity manager factories that are configured in accordance with the persistence.xml specification for the persistence unit.
A field or a method of an enterprise bean may be annotated with the PersistenceUnit annotation. The name element specifies the name under which the entity manager factory for the referenced persistence unit may be located in the JNDI naming context. The OPTIONAL unitName element specifies the name of the persistence unit as declared in the persistence.xml file that defines the persistence unit.
The following code example illustrates how an enterprise bean uses annotations to declare persistence unit references:
@PersistenceUnit EntityManagerFactory emf; @PersistenceUnit(unitName="InventoryManagement") EntityManagerFactory inventoryEMF;
The Bean Provider must use persistence unit references to obtain references to entity manager factories as follows.
Assign an entry in the enterprise bean's environment to the persistence unit reference.
The EJB specification RECOMMENDS, but does not require, that all persistence unit references be organized in the java:comp/env/persistence subcontexts of the bean's environment.
Lookup the entity manager factory for the persistence unit in the enterprise bean's environment using the EJBContext lookup method or using the JNDI API.
The following code sample illustrates obtaining an entity manager factory when the EJBContext lookup method is used:
@PersistenceUnit(name="persistence/InventoryAppDB") @Stateless public class InventoryManagerBean implements InventoryManager { @Resource SessionContext ctx; public void updateInventory(...) { ... // use context lookup to obtain entity manager factory EntityManagerFactory emf = (EntityManagerFactory) ctx.lookup("persistence/InventoryAppDB"); // use factory to obtain application-managed entity manager EntityManager em = emf.createEntityManager(); ... } }
The following code sample illustrates obtaining an entity manager factory when the JNDI APIs are used directly:
@PersistenceUnit(name="persistence/InventoryAppDB") @Stateless public class InventoryManagerBean implements InventoryManager { EJBContext ejbContext; public void updateInventory(...) { ... // obtain the initial JNDI context Context initCtx = new InitialContext(); // perform JNDI lookup to obtain entity manager factory EntityManagerFactory emf = (EntityManagerFactory) initCtx.lookup("java:comp/env/persistence/InventoryAppDB"); // use factory to obtain application-managed entity manager EntityManager em = emf.createEntityManager(); ... } }
Although a persistence unit reference is an entry in the enterprise bean's environment, the Bean Provider MUST NOT use an env-entry element to declare it.
Instead, if metadata annotations are not used, the Bean Provider must declare all the persistence unit references in the deployment descriptor using the persistence-unit-ref elements. This allows the ejb-jar consumer (i.e. Application Assembler or Deployer) to discover all the persistence unit references used by an enterprise bean. Deployment descriptor entries may also be used to specify injection of a persistence unit reference into a bean.
Each persistence-unit-ref element describes a single entity manager factory reference for the persistence unit. The persistence-unit-ref element consists of the optional description and persistence-unit-name elements, and the MANDATORY persistence-unit-ref-name element.
The persistence-unit-ref-name element contains the name of the environment entry used in the enterprise bean's CODE. The name of the environment entry is relative to the java:comp/env context (e.g., the name should be persistence/InventoryAppDB rather than java:comp/env/persistence/InventoryAppDB). The optional persistence-unit-name element is the name of the persistence unit, as specified in the persistence.xml file for the persistence unit.
The following example is the declaration of a persistence unit reference used by the InventoryManagerBean enterprise bean illustrated in the previous code sample:
<enterprise-beans> <session> <ejb-name>InventoryManagerBean</ejb-name> <ejb-class>com.wombat.empl.InventoryManagerBean</ejb-class> ... <persistence-unit-ref> <description> Persistence unit for the inventory management application. </description> <persistence-unit-ref-name> persistence/InventoryAppDB </persistence-unit-ref-name> <persistence-unit-name> InventoryManagement </persistence-unit-name> </persistence-unit-ref> ... </session> </enterprise-beans>
The Application Assembler can use the persistence-unit-name element in the deployment descriptor to specify a reference to a persistence unit. The Application Assembler (or Bean Provider) may use the following syntax in the persistence-unit-name element of the referencing application component to avoid the need to rename persistence units to have unique names within a Java EE application. The Application Assembler specifies the path name of the root of the referenced persistence unit and appends the name of the persistence unit separated from the path name by #. The path name is relative to the referencing application component jar file. In this manner, multiple persistence units with the same persistence unit name may be uniquely identified when persistence unit names cannot be changed.
For example:
<enterprise-beans> <session> ... <ejb-name>InventoryManagerBean</ejb-name> <ejb-class>com.wombat.empl.InventoryManagerBean</ejb-class> ... <persistence-unit-ref> <description> Persistence unit for the inventory management application. </description> <persistence-unit-ref-name> persistence/InventoryAppDB </persistence-unit-ref-name> <persistence-unit-name> ../lib/inventory.jar#InventoryManagement </persistence-unit-name> </persistence-unit-ref> ... </session> </enterprise-beans>
The Application Assembler uses the persistence-unit-name element to link the persistence unit name InventoryManagement declared in the InventoryManagerBean to the persistence unit named InventoryManagement defined in inventory.jar.
The following rules apply to how a deployment descriptor entry may override a PersistenceUnit annotation:
The relevant deployment descriptor entry is located based on the JNDI name used with the annotation (either defaulted or provided explicitly).
The persistence-unit-name overrides the unitName element of the annotation. The Application Assembler or Deployer should exercise CAUTION in changing this value, if specified, as doing so is likely to break the application.
The injection target, if specified, must name exactly the annotated field or property method.
![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |