JNDI, the ENC, and Injection (Enterprise JavaBeans 3.1)

 

Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise Naming Context (ENC). This is implemented by JNDI and is an object store where the EJB container can hold specific references to its environment. Think of it as the EJB container’s personal address book, where it writes down addresses to various Java EE services that it wants to look up and use within its business logic.

In previous topics, we started to talk a little bit about the ENC, showing how you can use annotations such as @javax.annotation.EJB and @javax.annotation.Resource to inject references to Java EE services directly into the fields of your bean. This injection process is driven by the EJB container’s ENC. In this topic, we show you how you can populate the ENC and use it as your own JNDI registry, and we show you how you can use it to inject environment references into your bean fields.

Global JNDI

While previous versions of the EJB Specification left it up to the vendor to decide exactly how clients were to look up session bean proxies. No matter which vendor’s implementation you choose, SLSBs and SFSBs views must be available in Global JNDI under this syntax:

tmp97189_thumb_thumb

In this arrangement, app-name refers to the name of the application (or EAR; this is optional), module-name is the name of the module (the JAR or WAR), and FQN is the fully qualified interface name. Elements in brackets are optional. So, for instance, an EJB outside of an enterprise archive and exposing a no-interface view would leave out app-name and FQN.

Let’s see an example:

tmp97190_thumb_thumb

We’ll assume that this EJB is packaged in a module, myejb.jar, which is located at the root of an encompassing application myapp.ear. Clients could then reliably expect to obtain a reference to the remote business interface by using the following code:

tmp97191_thumb1_thumb

This gives us a portable contract where we may expect to find our EJBs in the same place, no matter our vendor.

Although this works wonderfully for clients operating in nonmanaged environments, there are a few places we can improve this setup. For starters, the lookup code depends upon obtaining a vendor-specific JNDI Context. More importantly, we require a cast, and the lookup is not typesafe. Finally, because we must construct the JNDI name on our own, there’s a point for potential errors.

Luckily the EJB container provides a series of typesafe injection mechanisms, paving the way for a cleaner separation of logic from plumbing:

tmp97192_thumb_thumb

In many cases, this is all we need to obtain a usable reference. These injection facilities will be the focus of this topic.


The JNDIENC

The ENC has been around in the EJB specification since the early 1.0 days. It began as a local JNDI namespace that was specific to an EJB container. Developers could define aliases to resources, EJBs, and environment entries in the JNDI ENC through EJB XML deployment descriptors. These aliases could then be looked up directly in JNDI within business logic. In EJB 3.x, this mechanism was enhanced so that JNDI ENC references can be injected directly into the fields of a bean class. Annotations are the primary mechanism for doing this, but XML deployment descriptor support is available for those who wish to use that abstraction.

What Can Be Registered in the JNDI ENC?

Many different items can be bound to the ENC: references to any EJB interface, a JMS queue or topic destination, JMS connection factories, data sources, any JCA resource, and even primitive values. Java EE services such as javax.transaction.UserTransaction, javax.ejb.TimerService, and org.omg.CORBA.ORB are also available in the ENC.

How Is the JNDI ENC Populated?

The ENC’s JNDI namespace is populated in two separate ways: via XML or via annotations. Any reference that you declare in XML to a service or resource automatically populates the JNDI ENC with the reference’s name. Any environment annotation that you use in your bean class also causes the ENC to be populated. Once an item is bound to the JNDI ENC of the EJB container, it can be referenced by a JNDI lookup.

XML population

To illustrate how XML population works.Here we define a local interface reference from one EJB to another:

tmp97193_thumb1_thumb

The <ejb-local-ref> element tells the EJB container that the MyEJB wants a reference to the local business interface of MyEJB2. A reference to this bean is registered in the MyEJB’s JNDI ENC under the name ejbs/referenceToMyEJB2, as noted by the <ejb-ref-name> element. Other referenceable types such as resources and JMS destinations have elements similar to <ejb-local-ref> that specify how and where the reference will be bound into their JNDI ENCs. Each service type in Java EE has its own reference syntax. We’ll see examples of all of them in this topic.

Annotation population

Each referenceable type also has a corresponding annotation that can be used as an alternative to XML. If you specify these annotations on the bean class, they will cause the JNDI ENC to be populated with the information defined in the annotation:

tmp97194_thumb_thumb

In this example, we are registering a reference to the MyEJB2 under the ejb/reference ToMyEJB2 name. Business logic running inside the MyEJBBean is able to do JNDI lookups to find this reference. Each environment annotation, such as @javax.annotation.EJB, has a name() attribute that specifies the JNDI ENC name to which you want the service reference to be bound.

The second half of this topic describes all the details of each of these different environment annotations.

How Are Things Referenced from the ENC?

Anything registered in the JNDI ENC can be looked up by name under the java:comp/ env context. The comp part of this name corresponds to component. The JNDI name resolves to a different context depending on where you invoke the lookup. For example, if you invoke jndi.lookup(“java:comp/env”) within the MyEJB, you will get that EJB container’s ENC. If you do the same within another EJB, you will get a different ENC registry specific to that bean. The application server knows which ENC is active when you perform the lookup:

tmp97195_thumb_thumb

In this example, the lookupEjbFromEnc method needs a reference to MyEJB2. This reference was created in MyEJB’s ENC by annotating the bean class with the @EJB annotation, and the preceding code does a JNDI lookup to find this reference.

Using EJBContext

We talked a little bit about the javax.ejb.SessionContext and javax.ejb.MessageDrivenContext interfaces. Both extend the javax.ejb.EJBContext, and they can be used to look up ENC entries. The EJBContext interface has a convenience ENC lookup method, and it’s a bit simpler than a direct JNDI lookup because it does not throw a checked exception and it takes a relative name into the ENC instead of the full java:comp/env string we saw before. SessionContext or MessageDrivenContext can be injected into your session or message-driven beans by using the @javax.annotation.Resource annotation:

tmp97196_thumb_thumb

By using the @javax.ejb.EJB annotation on the otherBean field of the MyEJBBean class, the EJB container will automatically inject a reference when the bean instance is created.

tmp97197_thumb1_thumb

This example uses the EJBContext.lookup() method to look up the reference. This context object is injected into the ejbContext field using the @Resource annotation. Here we do not append the java:comp/env string to the name when performing the lookup but instead use the relative name defined in the annotation or XML reference.

Annotation injection

Instead of an ENC lookup, EJB references can be injected directly into a member variable. This injection can be done through environment annotations or an XML deployment descriptor fragment:

Unlike the previous example, when the bean instance is allocated, the EJB container will instead invoke the setOtherBean method, passing in the EJB reference as a parameter. This pattern works for all other injection annotations discussed in this topic. Setter method injection is more verbose than direct field injection, but its advantage is that it can be mocked more easily in unit tests.

A number of different environment annotations like @EJB are described in detail in the second half of this topic. All of them function similarly and follow the same usage patterns as @EJB.

Default ENC name

Annotating a field or a setter method of a bean class also creates an entry in the JNDI ENC for the injected element. This is true for all environment annotations, not just @EJB. If the name() attribute of the injection annotation is specified, then the reference is stored in the ENC under that name. If no name is specified, then the ENC name is extracted from the name of the annotated field or setter method. In this case, a default ENC name is derived from the fully qualified class name of the field or method, as well as the base name of the field or method. The ENC name becomes very important when you want to override an injection annotation within XML.

XML injection

If you prefer not to use annotations to initialize the fields of your bean class, then the <injection-target> element is available to you in your ejb-jar.xml deployment descriptor:

Alternatively, if you do not like this form of injection, the specification also supports injecting via a bean setter method:

tmp97198_thumb_thumb

tmp97199_thumb_thumbtmp97200_thumb1_thumb

Each XML environment element such as <ejb-local-ref> can use <injection-target> to populate a field or call a setter method with the referenced item. The <injec tion-target-class> element is the class where your field or method is declared. This may seem unnecessarily verbose, but this becomes important when there are inheritance hierarchies. The <injection-target-name> specifies the target field or method name into which you want the reference injected. In this case, we’re injecting into the otherBean field or setOtherBean method.

You cannot inject into a field and method with the same base name. In our example, you cannot simultaneously define injections upon an otherBean field and setOtherBean method, as they will represent the same ENC name and will not be distinguishable by the EJB container. If your logic requires injection into both a field and a method, simply assign different base names.

XML overrides

Using injection annotations is sometimes considered hardcoding configuration into the code of your bean class, though one could also make the argument that this is a static wiring of the application, not a configurable element. Either way, the EJB specification allows you to override injection annotations via the XML deployment descriptor. Let’s reexamine our use of the @EJB annotation:

tmp97201_thumb_thumb

In the original deployment of the MyEJB, the EJB container could figure out what EJB reference to inject based on the type of the annotated otherBean field. MyEJB2LocalBusiness was unique across the application. What if in a new deployment, multiple implementations of this type were deployed into the same application? You might want to configure, per deployment of your application, which reference is injected. You can override this annotation within XML:

tmp97202_thumb1_thumb

In this example, we are providing a more exact mapping tor the @EJB annotation within XML. The <ejb-ref-name> must match the default ENC name of the injected field; this is how the EJB container knows you are overriding an annotated field. The <ejb-link> element provides a more explicit reference to the EJB with the name MyEJB2.

If the name() attribute were used with the @EJB annotation, then <ejb-ref-name> would have to match that value. For example, consider this declaration in Java:

tmp97203_thumb1_thumb

The same nonDefaultReference name is referenced using the <ejb-ref-name> element.

tmp97204_thumb_thumb

The @EJB annotation tells the EJB container that it wants to inject an EJB with the MyEJB2LocalBusiness interface into the otherBean field, and that it should be registered in the ENC under the nonDefaultReference entry. The XML must use this ENC name to override what is injected:

XML always takes precedence over annotation metadata. XML provides the means to reconfigure hardcoded annotation configuration.

Injection and inheritance

It is possible for a bean class to be part of a class hierarchy. If any fields or methods have injection annotations on them, they will still be populated, but certain injection rules are followed:

tmp97205_thumb_thumb

In this example, we have a stateless session bean class that inherits from a base class. All instances of MySessionBean would have the appropriate resource injected into the base class’s someMethod method. It is possible to change what is injected by reimple-menting and overriding it in the subclass:

tmp97206_thumb1_thumb

The SomeEJB would no longer be injected into the someMethod method; instead, the new overridden reference, AnotherEJB, would be injected. There is one exception to this rule: if someMethod in the BaseClass was a private method rather than a protected or public method, then the base class would still be injected with the old reference.

Reference and Injection Types

The first half of this topic focused on the semantics of the JNDI ENC and how to reference things within it. You learned the base semantics of both annotation and XML injection. This section dives into the various services and configurations you can reference from your ENC. Other topics within this topic have touched briefly on most of these injectable and referenceable types, but this topic groups all of it into one place and discusses the intricacies and dirty details.

EJB References

As you saw earlier in this topic, your EJB bean classes can reference and aggregate other EJBs either through JNDI ENC lookups or by directly injecting these references into member fields.

@javax.ejb.EJB

The @javax.ejb.EJB annotation can be used on your bean class’s setter methods, on member fields, or directly on the class itself:

tmp97207_thumb_thumb

The name() attribute refers to what the JNDI ENC name will be for the referenced EJB. This name is relative to the java:comp/env context.

The beanInterface() attribute is the interface you are interested in and usually is used by the container to distinguish whether you want a remote or local reference to the EJB. If your EJB needs to be integrated with EJB 2.1 beans, beanInterface() can also be a reference to a home interface.

The beanName() is the EJB name of the EJB referenced. It is equal to either the value you specify in the @Stateless.name() or @Stateful.name() annotation or the value you put in the <ejb-name> field in the XML deployment descriptor.

The mappedName() attribute is a placeholder for a vendor-specific identifier. This identifier may be a key into the vendor’s global registry. Many vendors store references to EJBs within the global JNDI tree so that clients can reference them, and mappedName() may reference that global JNDI name.

The lookup() attribute, new to EJB 3.1, defines the JNDI name that should be used to find the target EJB reference. Although mappedName() for many vendors defines the same feature, this addition is spec-compliant.

As we’ve seen, when placed on the bean class, the @EJB annotation will register a reference into the JNDI ENC of the bean. In this scenario, the name() and beanInterface() attributes are required. Most of the time, only the bean’s interface is needed to distinguish which EJB you are referring to. Sometimes, though, you may be reusing the same business interface for multiple deployed EJBs. In that case, the bean Name() or lookup() (or, if your vendor supports it, mappedName()) attribute must be used to provide a unique identifier for the EJB you want to reference.

The @EJB annotation can be used only once on your bean class. When you need to reference multiple EJBs, the @javax.ejb.EJBs annotation is available:

tmp97208_thumb_thumb

This kind of annotation is required because only one annotation of a given type can be applied to any given artifact in the Java language. This plural name pattern is duplicated for the other reference annotations described in this topic:

tmp97209_thumb_thumb

In this example, we create an ENC reference to both the SomeEJB1 and SomeEJB2 beans through their local business views.

Ambiguous and overloaded EJB names

The <ejb-name> element and any @Stateless.name() or @Stateful.name() attributes must be unique within a given EJB-JAR deployment. Unfortunately, this is not the case for all EJB JARs deployed in an Enterprise ARchive (.ear) file. In an .ear file, EJB names can be duplicated in different EJB-JAR deployments. To differentiate references with duplicate EJB names, the EJB specification has an extended syntax for <ejb-link> and the beanName() attribute of the @EJB annotation. This extended syntax has a relative path to the JAR file in which the EJB is located, followed by the # character, followed by the EJB name of the referenced bean:

tmp97210_thumb_thumb

In this example, the myejbs.jar file is in the root directory of the EAR file along with the JAR the referencing EJB is deployed in. The @EJB annotation references SomeEJB specifically.

Resolving EJB references

The simplest example of the @javax.ejb.EJB annotation is using it with no other annotation attributes:

tmp97211_thumb_thumb

The specification isn’t very detailed in terms of exactly how the EJB container should resolve this reference. To give you a feel for how this process works, let’s see how the JBoss application server resolves this reference:

1. The only possible identifier for this EJB reference is the business interface type. The application server first looks for a unique EJB in the referencing EJB’s EJB-JAR deployment that uses SomeEJBLocalBusiness as one of its business interfaces. If more than one EJB uses the same business interface, it throws a deployment exception.

2. If the EJB-JAR is deployed as part of an Enterprise ARchive (.ear), it looks in other EJB-JARs for a unique EJB that uses the SomeEJBLocalBusiness interface. Again, if more than one EJB uses the same business interface, it throws a deployment exception.

3. If the EJB reference is not found in the .ear file, it looks for it in other global EJB-JAR deployments.

If the beanName() attribute is specified, then JBoss uses the same search process, but it uses the beanName()’s value as an additional identifier.

If the mappedName() or lookup() attribute is specified, then no search process is performed. The application server expects that a specific EJB is bound into the global JNDI under the attribute’s value.

EntityManagerFactory References

A javax.persistence.EntityManagerFactory can be registered in the JNDI ENC of an EJB and then injected. It is sometimes useful to obtain a reference to an EntityManager Factory directly so that you can have full control over the EntityManager instance and persistence context you want to work with. Although you can obtain an EntityManagerFactory through the javax.persistence.Persistence API, it is always better to use the facilities of Java EE so that the lifecycle of the EntityManagerFactory can be controlled by the application server. When you let the application server populate your ENC or inject your EntityManagerFactory, the Java EE runtime will handle the cleanup of this instance and you do not have to call EntityManagerFactory.close(). Like all other services and resources, an EntityManager Factory can be bound to the JNDI ENC or injected into your bean class by using either annotations or XML.

@javax.persistence.PersistenceUnit

The @javax.persistence.PersistenceUnit annotation can be used on your bean class’s setter methods or member fields, or directly on the class itself:

tmp97212_thumb_thumb

The name() attribute refers to what the JNDI ENC name will be for the referenced EntityManagerFactory. This name is relative to the java:comp/env context.

The unitName() attribute identifies which EntityManagerFactory you are interested in referencing and refers to the name given your persistence unit that you declared in a persistence.xml file. If left unspecified, a deployment error is raised, unless the EJB-JAR has only one persistence unit deployed within it. In that case, it defaults to this sole persistence unit.

When placed on the bean class, the @PersistenceUnit annotation will register a reference to the EntityManagerFactory in the JNDI ENC of the EJB bean class:

tmp97213_thumb_thumb

In this example, code within the MyEJBBean can look up an EntityManagerFactory that manages a MyDB persistence unit under the java:comp/env/persistence/MyDB JNDI ENC name. Here’s how a client bean would use this context to look up the reference to this EntityManagerFactory:

tmp97214_thumb_thumb

When the @PersistenceUnit annotation is used on the bean class, the name() attribute is always required so that the EJB container knows where in the JNDI ENC to bind the EntityManagerFactory.

The @PersistenceUnit annotation can be used only once on your bean class. So when you need to reference multiple persistence units, the @javax.persistence.PersistenceUnits annotation is available:

tmp97215_thumb_thumb

This is used just as we’ve seen with @EJBs; it allows us to aggregate a series of @PersistenceUnit annotations together.

The @PersistenceUnit annotation can also be placed on a setter method or member field so that the EntityManagerFactory that is referenced is injected directly into the bean class instance. When used on a setter method or member field, no annotation attribute is required, because both the name() and the unitName() attributes have valid defaults, as described earlier in this topic.

XML-based EntityManagerFactory references

The <persistence-unit-ref> element defines a reference to a given EntityManagerFactory. It contains the subelements <description> (optional), <persis tence-unit-ref-name> (required), and <persistence-unit-name> (required), as well as the element <injection-target> (optional) described in the first section of this topic. Here is an example of a reference that provides the same metadata as our annotation-based one shown earlier:

tmp97216_thumb1_thumb1

The <persistence-unit-ref-name> element is equivalent to the name() attribute of the @PersistenceUnit annotation, in that it represents the ENC name to which the reference will be bound. The <persistence-unit-name> element is equivalent to the unitName() attribute of the @PersistenceUnit annotation. It represents the same name you have declared in your persistence.xml deployment descriptor.

The <injection-target> element is used if you want to inject your EntityManagerFactory into your EJB’s bean class. Here is an example of using <injection-target>:

tmp97217_thumb_thumbtmp97218_thumb1_thumb1

In this example, the EntityManagerFactory would be injected into field named pu or passed as a parameter to a setter method named setPu() in the MyEJBBean class.

Scoped and overloaded unit names

A persistence unit can be declared in many different places. It can be defined in an EJB-JAR, an EAR/lib JAR, or even a WAR file. Persistence units are scoped when defined in a WAR or EJB-JAR file, and they cannot be referenced by components deployed outside of that archive. Persistence units deployed in a JAR in the .ears lib/directory are available to all other components in that enterprise archive. Sometimes you may have the same persistence unit name defined in your EJB or WAR file as the name you declared in a persistence JAR in the EAR/lib directory. To differentiate references with duplicate persistence unit names, the specification has an extended syntax for <persistence-unit-name> and the unitName() attribute of the @PersistenceUnit annotation. This extended syntax has a relative path to a JAR file that contains the persistence unit, followed by the # character, followed by the persistence unit name:

tmp97219_thumb_thumb

In this example, the myejbs.jar is in the same directory of the EAR file as the persistence unit’s JAR file. The @PersistenceUnit annotation references the MyDB persistence unit within that deployment.

EntityManager References

An EntityManager can be registered in the JNDI ENC of an EJB. When you are registering an EntityManager into the JNDI ENC or injecting it into your EJB, the EJB container has full control over the lifecycle of the underlying persistence context of the EntityManager. The EntityManager object reference itself is really just a proxy around an actual persistence context that may not even exist yet, depending on the type of persistence context you are injecting. When you let the application server populate your ENC or inject your EntityManager, the EJB container handles the cleanup of this instance and you do not have to call EntityManager.close(). In fact, it is illegal to call close() on an injected EntityManager instance, and an exception will be thrown if you do. Like all other services and resources, an EntityManager can be bound to the JNDI ENC or injected into your bean class by using either annotations or XML.

@javax.persistence.PersistenceContext

The @javax.persistence.PersistenceContext annotation can be used on your bean class’s setter methods or member fields or directly on the class itself:

tmp97220_thumb_thumb

The name() attribute refers to the JNDI ENC name under which the EntityManager is referenced. This name is relative to the java:comp/env context.

The unitName() attribute identifies which persistence unit you are interested in referencing. This identifier is the same as what you have declared in your persistence.xml file. If left unspecified, a deployment error is raised unless the EJB-JAR has only one persistence unit deployed within it. In that case, it defaults to this sole persistence unit.

The type() attribute specifies the type of persistence context you want. Persistence ContextType.TRANSACTION specifies that you want a transaction-scoped persistence context. This is the default. PersistenceContextType.EXTENDED gives you an extended persistence context. The EXTENDED type can be used only on stateful session beans. You will receive a deployment error if you use it with any other bean type.

The properties() attribute allows you to pass in additional vendor-specific properties for the created EntityManager instance. You set this attribute with an array of @javax.persistence.PersistenceProperty annotation declarations.

When placed on the bean class, the @PersistenceContext annotation will register a reference to the EntityManager into the JNDI ENC of the EJB bean class:

tmp97221_thumb_thumb

In this example, code within the MyEJB can look up an EntityManager that manages a MyDB persistence unit under the java:comp/env/persistence/MyDB JNDI ENC name. Here’s how a client bean would use this context to look up the reference to this EntityManager:

tmp97222_thumb_thumb

When the @PersistenceContext annotation is used on the bean class, the name() attribute is required so that the EJB container knows where in the JNDI ENC to bind the EntityManager. The type() and unitName() attributes have valid defaults.

The @PersistenceContext annotation can be used only once on your bean class. So when you need to reference multiple persistence contexts, the @javax.persistence.PersistenceContexts annotation is available.

The @PersistenceContext annotation can also be placed on a setter method or member field so that the EntityManager referenced is injected directly into the bean class instance:

tmp97223_thumb_thumb

When used on a setter method or member field, no annotation attribute is required, as the name(), unitName(), and type() attributes have valid defaults.

XML-based injection for EntityManager types works similarly to the previous examples for <persistence-unit-ref>.

Resource References

EJBs need access to more than just other EJBs and persistence contexts, and they use the JNDI ENC to look up external resources that they need to access. The mechanism for doing this is similar to the mechanism used for referencing other EJB and environment entries: the external resources are mapped into a name within the JNDI ENC namespace and are optionally injected into member fields or setter methods of bean instances. This is accomplished using annotations or an XML deployment descriptor fragment.

External resources can be of the following types:

• javax.sql.DataSource

• javax.jms.Queue

• javax.jms.Topic

• javax.jms.QueueConnectionFactory

• javax.jms.ConnectionFactory

• javax.jms.TopicConnectionFactory

• javax.mail.Session

• java.net.URL

• java.lang: String, Character, Byte, Short, Integer, Long, Boolean, Double, Float, Class, and all Enum types.

• javax.transaction.UserTransaction

• javax.transaction.TransactionSynchronizationRegistry

• CORBA ORB references

• JPA PersistenceUnit and PersistenceContext

In this section, we focus on javax.sql.DataSource as an example. @javax.annotation.Resource

The @javax.annotation.Resource annotation is used to reference an external resource. It can be applied to your bean class’s setter methods or member fields, or directly on the class itself. This annotation is highly overloaded and overused in the Java EE specification; in addition to external resources, it is also used to reference JMS message destinations, environment entries, EJBContexts, and Java EE core services. For now, we’ll focus solely on using this annotation to access external resources:

tmp97224_thumb1_thumb1tmp97225_thumb_thumb

The name() attribute refers to what the JNDI ENC name is for the referenced external resource. This name is relative to the java:comp/env context.

The type() attribute declares the fully qualified class name of the resource’s Java type. When the @Resource annotation is applied to the bean class, this attribute may be important to the EJB container to truly identify the resource in which you are interested. Usually, this attribute is unneeded and the default value is good enough.

The mappedName() attribute is a vendor-specific identifier for the external resource. Since Java EE has no specified mechanism or global registry for finding global resources, many vendors require this attribute so that they can locate and bind the resource. Many times, this mappedName() attribute will be equivalent to a global JNDI name.

The lookup() attribute, new in JEE6, is the spec-defined mechanism pointing to a resource in global JNDI.

When placed on the bean class, the @Resource annotation registers a reference to the external resource into the JNDI ENC of the EJB bean class:

tmp97226_thumb_thumb

In this example, the @Resource annotation is binding a javax.sql.DataSource into the jdbc/PostgresDB ENC name. The lookup() attribute provides the global JNDI name so that the application server can locate the desired resource. Code within the MyEJB can now locate this data source under the java:comp/env/jdbc/PostgresDB JNDI ENC name.

When the @Resource annotation is used on the bean class, the name() and type() attributes are required. Here lookup() is used to truly identify the resource.

The authenticationType() attribute tells the server who is responsible for authentication when the resource is accessed. It can have one of two values: CONTAINER or APPLICATION. If CONTAINER is specified, the container will automatically perform authentication (sign on or log in) to use the resource, as specified at deployment time. If APPLICATION is specified, the bean itself must perform the authentication before using the resource. Here’s how a bean might sign on to a connection factory when APPLICATION is specified:

tmp97227_thumb_thumbtmp97228_thumb1_thumb

In this case, the connection will be authenticated programmatically. In the CONTAINER option, the caller principal could be extracted internally by the resource itself or configured statically by the application deployment.

The @Resource annotation can be used only once on your bean class. When you need to reference multiple persistence units, the @javax.annotation.Resources annotation is available.

The @Resource annotation can also be placed on a setter method or member field so that the resources referenced will be injected directly into the bean class instance. When used on a setter method or member field, only the lookup() attribute may be required to identify the resource, as the type and ENC name can be determined from the type and name of the method or field.

Shareable resources

When several enterprise beans in a transaction use the same resource, you will want to configure your EJB server to share that resource. Sharing a resource means that each EJB will use the same connection to access the resource (e.g., database or JMS provider), a strategy that is more efficient than using separate resource connections.

In terms of a database, EJBs that are referencing the same database will probably want to use the same database connection during a transaction so that all create, read, update, and delete (CRUD) operations return consistent results. EJB containers share resources by default, but resource sharing can be turned on or off explicitly with the shareable() attribute of the @Resource annotation.

Occasionally, advanced developers may run into situations where resource sharing is not desirable, and having the option to turn off resource sharing is beneficial. But unless you have a good reason for turning off resource sharing, we recommend that you accept the default shareable() setting of true.

Resource Environment and Administered Objects

Resource environment entries are objects that do not fall into the resource reference category. Some resources may have other, additional administered objects that need to be obtained from the JNDI ENC or injected into your bean class. An administered object is a resource that is configured at deployment time and is managed by the EJB container at runtime. They are usually defined and deployed by a JCA resource adapter.

Besides administered objects, resource environment entries are also used to reference services such as javax.transaction.UserTransaction and javax.transaction.TransactionSynchronizationRegistry.

To obtain a reference to one of these services, the @Resource annotation can be used. When using this annotation, the authenticationType() and shareable() attributes are meaningless and are illegal even to specify.

Environment Entries

The EncryptionEJB had a configurable property for the cipher’s passphrase. These types of configurable properties are called environment entries. The bean can use environment entries to customize its behavior.

Although they can be defined using annotations, environment entries are almost always configured via XML, as they really are configuration values and not metadata. The <env-entry> element is used to define them. This element contains the subelements <description> (optional), <env-entry-name> (required), <env-entry-type> (required), and <env-entry-value> (optional), as well as the element <injection-target> (optional). Here is a typical <env-entry> declaration:

tmp97229_thumb_thumb

The <env-entry-name> element is relative to the java:comp/env context. For example, the ciphersPassphrase entry can be accessed using the path java:comp/env/ciphers Passphrase in a JNDI ENC lookup:

tmp97230_thumb_thumb

Alternatively, it can be looked up with the EJBContext.lookup() method using the ciphersPassphrase name.

<env-entry-type> can be of type String or one of the several primitive wrapper types, including Integer, Long, Double, Float, Byte, Boolean, Short, or any Enum type.

<env-entry-value> is optional. The value can be specified by the bean developer or deferred to the application assembler or deployer.

The <injection-target> element can be used to initialize a field or setter method with the environment entry’s value:

tmp97231_thumb_thumb

The preceding XML will inject the value OverriddenPassword into the field named ciphersPassphrase or invoke a setter method named setCiphersPassphrase in the bean class.

The @javax.annotation.Resource annotation can be used to pull in the environment entry instead of the <injection-target> element:

tmp97232_thumb_thumb

In this example, the value will be pulled from the environment entry described in XML and injected into the passphrase field. If no XML is used to configure this value, the default will be “defaultPassphrase”, but no entry is created in the ENC. A common pattern is to annotate your field with @Resource and provide a default value for the field that can optionally be overridden in XML. Using the @Resource annotation with a String or primitive value type identifies it as an environment entry to the EJB container. When @Resource designates an environment entry, only the name() attribute is allowed to be specified. Also, it doesn’t make much sense to use @Resource for environment entries at the class level, as there is no way to initialize the value in the annotation.

Message Destination References

Message destination references populate the JNDI ENC with a pointer to a JMS topic or queue. You need these references if you are sending messages within your EJB.So only an overview will be provided here, with additional instructions on how to inject using an annotation instead.

XML-based resource references

The <message-destination-ref> element defines a reference to a JMS message destination. It contains the subelements <description> (optional), <message-destination-ref-name> (required), <message-destination-type> (required), <message-destination-usage> (required), <message-destination-link> (optional), and <mapped-name> (optional), as well as the element <injection-target> (optional) described in the first section of this topic. Here is an example of a reference to a topic:

tmp97233_thumb1_thumb1

The <message-destination-ref-name> element is the JNDI ENC name the topic will be bound to and is relative to the path java:comp/env.

The <message-destination-type> element is either a javax.jms.Topic or a javax.jms.Queue and is required.

The <message-destination-usage> element specifies whether the EJB produces or consumes messages to or from this destination.

The <message-destination-link> element creates a message flow.

Sometimes a vendor-specific identify is required, and <mapped-name> optionally fulfills this role.

As with all other resource reference types, the <injection-target> element can be used to inject the destination into a field or setter method.

Using @Resource

The @javax.annotation.Resource annotation is overloaded to support referencing JMS destinations. Unfortunately, the specification does not provide annotation metadata to set up a message destination link, so you’ll have to rely on XML to do this sort of thing.

When placed on the bean class, the @Resource annotation registers a reference to the JMS queue or topic destination into the JNDI ENC of the EJB bean class:

tmp97234_thumb_thumb

In this example, the @Resource annotation is binding a javax.jms.Topic into the jms/ MyTopic ENC name. The mappedName() attribute provides a global, vendor-specific identifier so that the application server can locate the desired destination.

When the @Resource annotation is used on the bean class, the name() and type() attributes are required. As stated earlier, lookup() may be required by the vendor to truly identify the resource from global JNDI. Only these three attributes can be set by application code. All others are illegal, and they will create a deployment error.

The @Resource annotation can also be placed on a setter method or member field so that the destination referenced will be injected directly into the bean class instance:

tmp97235_thumb_thumb

When used on a setter method or member field, only the lookup() attribute may be required to identify the resource, as the type and ENC name can be determined from the field type and name.

Next post:

Previous post: