Programming


Programming

Overview

Figure 4-6 provides a complete overview of the classes and interfaces for the case of the remote client view. To the right is the session bean class, and to the left are the interfaces that are also available to the client and are implemented via the home or remote object of the EJB container (see also Chapter 3). The methods in the figure whose names are struck through cannot be sensibly implemented with session beans. They are conceived for entity beans.

click to expand
Figure 4-6: Interfaces of a session bean with remote client view.

The session bean class implements the interface javax.ejb.SessionBean. The bean developer implements this class, which realizes the functionality of the session bean. There is no actual constructor and no finalize method in the bean class. If a constructor is defined, it must be declared public, and it is not permitted to have any parameters (default constructor) Constructors are generally not used in implementing EJB components.

The home and remote objects belong to the container classes and are generated (cf. Chapter 3). The bean developer defines the associated home and remote interfaces. The bean's home interface inherits from the interface javax.ejb.EJBHome, while the remote interface inherits from javax.ejb.EJBObject.

Figure 4-7 provides a complete overview of the classes and interfaces for the case of the local client view. To the right is the session bean class, and to the left are the interfaces used by the client and implemented via the local home and local objects of the EJB container (see also Chapter 3). The struck-through methods in the figure cannot be used sensibly with session beans. They are conceived for entity beans. In the case of the local client view the session bean class is identical to that of the remote client view.

click to expand
Figure 4-7: Interfaces of a session bean with local client view.

The local home and local objects belong to the container classes and are generated (cf. Chapter 3). The bean developer defines the associated local home and local interfaces. The bean's local home interface inherits from the interface javax.ejb.EJBLocalHome. The local interface inherits from the interface javax.ejb.EJBLocalObject.

A session bean could implement the remote as well as the local client view. However, according to the specification an enterprise bean should implement either the local or the remote client view; not both.

All the methods of the bean class as well as the home and remote interfaces can be divided into three groups:

  • state management;

  • identity management;

  • application logic.

The following subsections describe the individual methods in these groups. In addition, the session context and the interfaces that the client program uses will be introduced. Those interested in a more rapid plunge into the subject may skip the following descriptions on a first reading. The program examples for session beans give the reader a rapid entry into practical programming.

State Management

In Figures 4-6 and 4-7 the methods for state management are listed first. These methods are called by the EJB container to notify the bean instance of a state transition. These methods implement the logic that prepares the bean instance for the new state.

Both the actions of the client and the internal processes of the EJB container can trigger the state transition that leads to these method calls. The client, however, does not obtain direct access to these methods.

void setSessionContext(SessionContext ctx)

The method setSessionContext is called by the EJB container after the creation of the bean instance. The EJB container transfers to the session bean its SessionContext. The implementation of this method has the task of storing the SessionContext. Further initialization steps should normally not be taken here. The passed object of the class SessionContext defines the environment of the bean instance (see also the later section on session context).

void ejbPassivate()

The method ejbPassivate is called by the EJB container before it passivates a stateful session bean instance. Stateless session beans do not need this method and leave the implementation empty, since these methods are invoked by the EJB container only for stateful session beans.

The method is used to bring the bean instance into a state suitable for passivation. The additional resources that were used by the bean instance must be released. For example, network or database connections must be closed. All references and additional resources (other enterprise beans, network connections, database connections, etc.) should be declared transient by the developer. If this has not occurred, these references must be initialized to null. The preceding section, on the conversational state, gives the precise conditions that a bean must satisfy for passivation.

Note that the method ejbPassivate is not executed in a transaction. The EJB container ensures that no bean instance within a transaction is passivated. Thus at the time of passivation the conversational state of the bean instance receives no data that need to be protected with a transaction. The passivation must thereby also be possible without transactions.

If an error occurs in this method that prevents the passivation of the bean instance, then the exception javax.ejb.EJBException should be triggered (with EJB 1.0 the exception java.rmi.RemoteException is still used). The EJB container considers this exception a system error and destroys the bean instance.

void ejbActivate()

The method ejbActivate is the complement of ejbPassivate. The EJB container calls this method after it has reloaded a passivated bean instance into active memory.

This method is used to reserve additional resources that were released during passivation. For example, network or database connections can be reopened.

As with ejbPassivate, with ejbActivate no transaction is available. Error handling is analogous to that of ejbPassivate.

Identity Management

The methods for identity management constitute the second group in the figures. They enable the generation and deletion of session bean identities. These methods are again located in the local home, local, home, and remote home interfaces and are available to the client even before it has a bean instance.

void ejbCreate(...)

The client obtains a bean instance through a create call in the home or local home interface. Stateful session beans can offer several create methods, which are distinguished by their signatures. Stateless sessions beans have only one create method, without parameters. After the EJB container has generated a new bean instance, it calls its ejbCreate method. In the case of stateful session beans it relays the client's create call to the bean's ejbCreate method with the appropriate signature.

The bean developer defines the create methods in the home and local home interfaces and implements the ejbCreate methods in the bean class. The signatures of the methods in the bean class and in the home and local home interfaces must be identical. The implementation of the ejbCreate methods has the task of initializing the bean instance. A stateful session bean instance initializes the conversational state using parameters.

The methods are not part of the interface javax.ejb.SessionBean, since the signatures differ for each bean class. Each method is announced to the EJB container in the deployment descriptor.

void ejbRemove()

The client gives the order to delete a session bean identity by a call to the method remove in the remote or local interface. If it is working with a Handle (see the later subsection on the client), it can also use the method remove(Handle) in the home interface (remote client view only). The method remove(Object) in the home interface is reserved for entity beans and cannot be used by session beans.

In the case of stateful session beans a client call by the EJB container is relayed to the method ejbRemove of the relevant bean instance. In the case of stateless session beans the EJB container is not directly ordered by the client to call the method ejbRemove.

The method remove is defined in javax.ejb.EJBObject and javax.ejb.EJBLocalObject; the bean developer implements ejbRemove in the bean class. The implementation of ejbRemove releases reserved resources. After a call to the method the bean instance is deleted.

The method ejbRemove can be called by the EJB container with a transaction. The associated transaction attribute in the deployment descriptor defines the behavior of the EJB container (see Chapter 7 on transactions).

Application Logic

The third group in the figure is that of the methods for the application logic, which are also found in the remote and local interfaces. These methods are implemented in the bean class by the bean developer. The definition in the bean class has the same signature as the definition in the remote or local interface.

The EJB container controls all calls to the methods of a bean. It relays the client calls to the relevant methods of the bean class. The client never accesses the bean instance directly. The transaction attributes in the deployment descriptor define the transaction context in which the methods are executed.

In these methods the bean developer implements the actual logic of the session bean. In contrast, all previously discussed methods fulfill only management tasks.

If an irremediable error occurs in the application logic, a java.ejb.EJBException must be triggered. The EJB container considers this a system error and destroys the bean instance.

The Session Context

Every session bean instance has an object of the class javax.ejb.SessionContext that is made available to it by the EJB container in the method setSessionContext. The session context defines the environment of the bean instance. The session bean instance uses the transmitted session context for its entire lifetime. The EJB container can change the session context of a bean instance and thereby allocate to it an altered environment. If, for example, various clients use an instance of a stateless session bean one after the other, the EJB container sets the identity of the client in the session context before each method call.

The session context enables the bean instance to access the home object, the identity of the client, and the active transaction. In what follows the most important methods from the interface SessionContext will be presented. A complete description can be obtained in the EJB specification (see [21]).

EJBHome getEJBHome()

The method getEJBHome enables the bean instance to access its own home interface. The data type of the return value must be converted into the special home interface of the bean class. This method triggers an exception of type java.lang.IllegalStateException if the session bean has no home interface (but instead a local home interface).

EJBLocalHome getEJBLocalHome()

The method getEJBLocalHome enables the bean instance to access its own local home interface. The data type of the return value must be converted to the special local home interface of the bean class. This method triggers an exception of type java.lang.IllegalStateException if the session bean has no local home interface (but instead a home interface).

void setRollbackOnly()

The method setRollbackOnly serves to control transactions (see Chapter 7). A bean instance uses this method in the case of an error to ensure that the active transaction is terminated with a rollback.

boolean getRollbackOnly()

The method getRollbackOnly is the "read" complement to the method setRollbackOnly. With getRollbackOnly it can be checked whether it is still possible to terminate the active transaction with Commit.

UserTransaction getUserTransaction()

Normally, the EJB container takes control over transactions. The method getUserTransaction requires a bean instance only if it wishes to take over the transaction control itself. The return value of the method is an object of the class transaction.UserTransaction, which enables access to the transaction context (see Chapter 7).

Principal getCallerPrincipal()

The method getCallerPrincipal permits a bean instance to determine which user has announced itself to the client. The return value is an object of the class java.security.Principal (see Chapter 8).

boolean isCallerInRole(java.lang.String roleName)

With this method a check is made as to whether the announced user has a particular role in the security concept. The possible roles are defined in the deployment descriptor (see Chapter 8).

The Client

Naming Service as Object Store

A naming service manages name-value pairs in a namespace. Each name in the namespace is unique and identifies a particular value. The EJB concept uses the naming service for management of the home object and other resources. The home objects is stored as a value and entered under the name of the bean in the naming service (this holds for the local and remote client views). Each client can thereby request the bean's home object from the naming service if it knows the name of the bean. It then receives indirect access to the bean via the home object.

For access by Java to the naming service, JNDI (Java Naming and Directory Interface) is available. The interface was defined by Sun Microsystems and has belonged to the Java development kit (JDK) since JDK version 1.2.

In practice, a separate naming service, addressed via JNDI, is integrated into many application servers. The use of an external naming service can nonetheless also be a good idea. JNDI supports the following protocols:

  • RMI Registry (Java Remote Method Invocation);

  • LDAP (Lightweight Directory Access Protocol);

  • COS (CORBA Services Naming Service).

To obtain access to JNDI, the class javax.naming.InitialContext is used. This class implements the interface javax.naming.Context. Every instance of this class has a preinitialized namespace, which is initialized with data from two sources:

  • In the constructor a hash table object can be passed. Its name-value pairs are transferred into the namespace of InitialContext.

  • The file jndi.properties in the class path likewise contains name-value pairs. These are also taken in.

Certain name-value pairs from the hash table object that is passed in the constructor are not simply taken into the namespace, but serve for the initialization of JNDI. The interface Context defines the needed constants that define the names that are used:

  • INITIAL_CONTEXT_FACTORY: The name of a class must always be stored under this name, which serves as a factory (cf. design pattern factory in [5]) for a name service. The value required here must be provided by every creator of an EJB container or naming service.

  • PROVIDER_URL: Here a URL is defined for the naming service. The URL is a string that contains the network name of the server and the port that is used. The creator of the naming service must provide precise information on the form of this URL.

  • SECURITY_PRINCIPAL: Here the user name for the naming service is defined. Depending on the configuration of the naming service it can also be possible to work without user names.

  • SECURITY_CREDENTIALS: Here the associated password to the declared user name is defined.

The following import instructions are necessary in our case for us to be able to use JNDI:

import javax.naming.Context;
import javax.naming.InitialContext;
 

Listing 4-1 shows a method that a client program could use for the initialization of InitialContext. The boldface strings in the listing should be replaced by the appropriate values, depending on the server used.

Listing 4-1: getInitialContext: Initialization for JNDI access.

start example
final static String ctxUser = "CtxUser";
final static String ctxPassword = "CtxPassword";
final static String ctxFactory = "CtxFactory";
final static String ctxUrl = "CtxURL";
/**
 * Fetches and initializes InitialContext.
 * The method uses the
 * following variables:
 * ctxUser, ctxPassword,
 * ctxFactory, ctxUrl
 *
 *@return Context - InitialContext Object
 *@exception javax.naming.NamingException
 */
static public Context getInitialContext()
  throws javax.naming.NamingException
{
  Hashtable p = new Hashtable();

  p.put(
    Context.INITIAL_CONTEXT_FACTORY,
    ctxFactory);
  p.put(
    Context.PROVIDER_URL,
    ctxUrl);
//This part is optional
  p.put(
    Context.SECURITY_PRINCIPAL,
    ctxUser);
    p.put(
      Context.SECURITY_CREDENTIALS,
      ctxPassword);
  //This part is optional

    return new InitialContext(p);
}
 
end example

Access to a Session Bean

With the aid of the naming service a client obtains access to the home or local home interface. With a call to the method lookup on a Context object it passes the bean's unique JNDI name as parameter and receives as return value the implementation of the home or local home interface. The JNDI name of an enterprise bean is set at deployment, and the allocation of the JNDI name is creator-specific.

The return value of the method lookup has the data type Object. In the case of the local client view the return value can be converted with type casting into the type of the local home interface. With the remote client view this cannot easily be done. Since version 1.1 of the EJB specification introduced support for RMI-IIOP, an extra level of conversion and casting of remote objects has been required for complete compatibility between all systems.

For the proper conversion of data types there is the method narrow of the class javax.rmi.PortableRemoteObject. This class has belonged to the standard language since Java version 1.3. For older versions of Java one can fall back on the RMI-IIOP mapping. The process for data type conversion of the home interface is always the same, and this conversion is demonstrated in Listing 4-2. After the home interface is recognized, the client can create a new bean, and it receives as return value the bean's remote interface. The client can work with the bean via the remote interface almost as if it were a local object and were not being executed on the server. After the bean has been used, it must be deleted (remove).

Listing 4-2: Client access to a session bean (remote client view).

start example
 ...
javax.naming.Context ctx;
String beanName = "BeanName";
 HomeInterfaceClass home = null;
 RemoteInterfaceClass bean = null;
try {
  ctx = getInitialContext();
  home = (HomeInterfaceClass)
    javax.rmi.PortableRemoteObject.narrow(
    ctx.lookup(beanName),
    HomeInterfaceClass.class);
  bean = home.create(...);
  ...
  bean.remove();
}
catch(javax.ejb.CreateException e){
  System.out.println(
    "Bean generation error");
}
catch(javax.ejb.RemoveException e){
  System.out.println(
    "Bean removal error");
}
catch(javax.naming.NamingException e) {
  System.out.println(
    "Name service reports an error");
}
catch(RemoteException e) {
  System.out.println(
    "Problem with the network connection");
}
...
 
end example

Listing 4-3 demonstrates the use of a session bean with the local client view.

Listing 4-3: Client access to a session bean (local client view).

start example
...
javax.naming.Context ctx;
String beanName = "LocalBeanName";
 LocalHomeInterfaceClass home = null;
 LocalBeanInterfaceClass bean = null;
try {
  ctx = getInitialContext();
  home = (LocalHomeInterfaceClass)
             ctx.lookup(beanName);
  bean = home.create(...);
  ...
  bean.remove ();
}
catch(javax.ejb.CreateException e){
  System.out.println(
    "Bean generation error");
}
catch(javax.ejb.RemoveException e){
  System.out.println(
    "Bean removal error");
}
catch(javax.naming.NamingException e) {
  System.out.println(
    "Name service reports an error");
}
...
 
end example

The Identity of a Session Bean

The client uses the identity of session beans only to determine whether two references are to point to the same or different bean instances. The uses of stateless and stateful session beans are different here, and they will be described in what follows.

Every stateful session bean has its own identity, which is an ID that the EJB container uses for internal management of instances. The ID itself is not accessible by the client. For comparing session beans the EJB container makes available to the client an implementation of the method isIdentical, which is defined in the interface javax.ejb.EJBObject or javax.ejb.EJBLocalObject as follows:

public abstract boolean isIdentical (EJBObject obj);
 

or

public abstract boolean isIdentical (EJBLocalObject obj);

 

Listing 4-4 demonstrates the use of the method for stateful session beans in the case that the session bean has a remote interface. The use of the method isIdentical for local interfaces is similar.

Listing 4-4: Comparison of identities of stateful session beans.

start example
// Fetch the HomeObject using JNDI
StatefulBeanHome homeObject = ...;

// generate two
// stateful session beans
StatefulBean sfb1 = homeObject.create(...);
StatefulBean sfb2 = homeObject.create(...);

// comparison of identities
if (sfb1.isIdentical(sfb1)) {
// This comparison yields "true".
}
if (sfb1.isIdentical(sfb2)) {
// This comparison yields "false".
}
 
end example

In contrast to stateful beans, individual instances of a stateless session bean are not distinguished by a conversational state. The EJB container views all instances of a stateless session bean that have the same home or local home interface as equivalent, since they are interchangeable. Therefore, all instances of a stateless session bean class have a common identity. Listing 4-5 clarifies this relationship for the case that the session bean has a remote interface. Here, too, the application in the case of local interface is similar.

Listing 4-5: Comparison of identities of stateless session beans.

start example
//Fetch the HomeObject using JNDI
StatelessBeanHome homeObject = ...;

// Create two stateless session beans
StatelessBean slb1 = homeObject.create(...);
StatelessBean slb2 = homeObject.create(...);

// Compare identities
if (slb1.isIdentical(slb1)) {
// This comparison yields "true".
}
if (slb1.isIdentical(slb2)) {
// This comparison yields "true".
}

 
end example

Handles

Handles are of relevance only in the case of the remote client view. They are deployed when a reference to the home or remote interface is necessary that can also be used externally to the client process. Handles can be sent or stored beyond the lifetime of the client. A handle can be understood as a serializable reference to a remote or home object. The existence of a handle object does not, however, influence the life cycle of the bean instance. When the bean instance is deleted (under the control of the client or after a timeout) the handle object becomes invalid.

To create a handle every remote interface possesses a method getHandle, which returns a handle object to the remote interface of this bean instance (see Listing 4-6). The corresponding method in the case of a home object is getHomeHandle. Handle objects have for their part a method getEJBObject, whose return value is the bound remote object of the bean.

Listing 4-6: Use of a remote handle.

start example
...
try{
  javax.ejb.Handle handle;

  // get Handle
  Handle handle = remote.getHandle();

// get Remote-Object with handle
  RemoteClass remote = (RemoteClass)
    javax.rmi.PortableRemoteObject.narrow(
    handle.getEJBObject(),
    RemoteClass.class);
}catch(RemoteException e){
  // cannot get handle
}
...
 
end example

However, the EJB container cannot take into account the existence of a handle in managing the bean instances. After a configured time interval has elapsed (timeout) every session bean is deleted by the EJB container. The attempt to access a deleted instance leads to a RemoteException.

The Bean's Environment

A bean is always executed in a defined environment. All bean instances of a class that have the same home or local home interface have the same environment. The environment of a bean consists of the following components:

  • Environment variables for configuration values;

  • References to other bean classes;

  • Resources of the EJB container;

  • Administered objects.

The bean developer determines what properties the environment of the bean will have. He determines which configuration parameters the bean will have, with what other beans it will work, and what EJB container resources it will use. On this basis the application assembler and the deployer define the concrete run-time environment. They determine the values for the configuration, select the bean classes for the references, and configure the available services.

At run time the EJB container provides the bean instance with its environment in a naming service. Among the defined names the bean instance finds the individual components of its environment. The process is comparable with the client's access to JNDI. The EJB container provides the bean with the suitable InitialContext, so that it can access its own environment.

The Enterprise Edition of Java, version 2 (J2EE) suggests a convention for naming the various services in the naming service. The following names should be used, since version 1.1, by EJB-conforming servers:

  • java:comp/env/— Environment variables;

  • java:comp/env/ejb— References to other bean classes;

  • java:comp/env/jdbc— Access to JDBC databases;

  • java:comp/env/jms— Access to Java messaging service topics and queues;

  • java:comp/env/mail— Access to JavaMail resources;

  • java:comp/env/url— Access to web servers and related services.

Environment Variables

The bean developer can provide for a later configuration of a bean. To this end environment variables (description, name of the variable, data type)are defined, to which the application assembler or deployer must assign values (value). Only certain simple data types are allowed: String, Integer, Boolean, Double, Byte, Short, Long, Float. The data type must be completely specified in the deployment descriptor (see Listing 4-7).

Listing 4-7: Schematic deployment descriptor with the definition of an environment variable.

start example
...
<enterprise-beans>
  <session>
    ...
    <env-entry>
      <description>
        description
      </description>
      <env-entry-name>
        name
      </env-entry-name>
      <env-entry-type>
        data type
      </env-entry-type>
      <env-entry-value>
        value
      </env-entry-value>
      ...
      </env-entry>
    </session>
  </enterprise-beans>
  ...
 
end example

At run time a bean instance can access its environment variables via JNDI (see Listing 4-8). The variable can be found under its name in the path java:comp/env/ (see Listing 4-8).

Listing 4-8: Schematic of selected environment variables.

start example
javax.naming.Context beanCtx =
  new javax.naming.InitialContext();
 data type something = (data type)
  beanCtx.lookup("java:comp/env/name");

 
end example

References

A bean has the option of using other beans. With EJB version 1.1 the management of these dependencies was improved, and EJB version 2.0 further strengthened the use of this new concept. The bean developer addresses other beans only with a logical name. He defines all references to other beans in the deployment descriptor (description, reference name, bean type: session or entity).

Only later does the application assembler define which bean will actually be used. For this he extends the definition in the deployment descriptor. He names the referenced bean (ejb-link). Here the name of the bean in the deployment descriptor (as in ejb-name) is used. If a bean in another deployment descriptor is referred to, then here is given the path and name of this deployment descriptor, followed by the # symbol and the name of the bean (as in ejb-name). Alas, we must state here that the procedure that we have described is not followed with the same degree of punctiliousness by all producers of EJB containers, and sometimes proprietary interfaces must be used.

Listing 4-9 shows the definitions in the deployment descriptor of the bean provider and application assembler for a reference to a bean with remote interface. Listing 4-10 shows analogously the definitions for a reference to a bean with local interface.

Listing 4-9: Schematic deployment descriptor with reference to another bean (remote interface).

start example
...
<enterprise-beans>
  <session>
    ...
    <ejb-ref>
      <description>
        description
      </description>
      <ejb-ref-name>
        ejb/reference name
      </ejb-ref-name>
      <ejb-ref-type>
        session or entity
      </ejb-ref-type>
      <home>
        HomeInterface
      </home>
      <remote>
        RemoteInterface
      </remote>
      <ejb-link>
        name of the referenced bean
      </ejb-link>
    </ejb-ref>
    ...
  </session>
</enterprise-beans>
...
 
end example

Listing 4-10: Schematic deployment descriptor with reference to another bean (local interface).

start example
...
<enterprise-beans>
  <session>
    ...
    <ejb-local-ref>
      <description>
        description
      </description>
      <ejb-ref-name>
         ejb/reference name
      </ejb-ref-name>
      <ejb-ref-type>
        session or entity
      </ejb-ref-type>
      <local-home>
        LocalHomeInterface
      </local-home>
      <local>
        LocalInterface
      </local>
      <ejb-link>
        name of the referenced bean
      </ejb-link>
    </ejb-local-ref>
    ...
  </session>
</enterprise-beans>
...

 
end example

At run time the bean instance can access the referenced beans via JNDI. The referenced bean's home or local home interface can be found under its logical name in the path java:comp/env/ejb. Listing 4-11 clarifies this relationship using a reference to a bean with remote interface. The modus operandi with a reference to a bean with local interface is analogous; in such a case use of the method narrow can be avoided.

Listing 4-11: Schematic use of reference to another bean.

start example
...
javax.naming.Context beanCtx =
  new javax.naming.InitialContext();
Object temp = beanCtx.lookup(
  "java:comp/env/ejb/reference name");
 HomeInterface home = (HomeInterface)
  javax.rmi.PortableRemoteObject.narrow(
  temp, HomeInterface.class);
...
 
end example

Resources

The EJB container offers access to various resources as services. For each resource it provides a resource factory, with the help of which the bean obtains access to the service. To clarify the mechanisms we shall explain the use of a JDBC database.

A bean has the ability to address a database directly. So that a bean can be used in a variety of applications, since version 1.1 a flexible configuration has been provided for. The bean developer defines only one logical name for the database in the deployment descriptor (name, description, security strategy: application or container). Moreover, the developer can specify (via the optional element res-sharing-scope) whether connections to the database from this resource can be shared with other enterprise beans.

The deployer uses tools of the EJB container to determine later the actual database, which is allocated in the reference in Listing 4-12.

Listing 4-12: Schematic deployment descriptor with reference to a JDBC database.

start example
...
<enterprise-beans>
  <session>
    ...
    <resource-ref>
      <description>
        description
      </description>
      <res-ref-name>
        jdbc/reference name
      </res-ref-name>
      <res-type>
        javax.sql.DataSource
      </res-type>
      <res-auth>
        Application or Container
      </res-auth>
      <res-sharing-scope>
        Shareable or Unshareable
      </res-sharing-scope>
    </resource-ref>
      ...
  </session>
</enterprise-beans>
...
 
end example

If the application server also manages additional resources with JNDI, then additionally, only the logical name must be mapped to the correct JNDI name. Listing 4-13 shows what an application server might look like in this configuration language.

Listing 4-13: Mapping the logical name to the JNDI name of the resource.

start example
<reference-descriptor>
  <resource-description>
    <res-ref-name>
      jdbc/reference name
    </res-ref-name>
    <jndi-name>
      JNDI name: Database
    </jndi-name>
  </resource-description>
</reference-descriptor>
 
end example

At run time the bean can obtain access to the referenced JDBC database via JNDI. The resource factory can be found under its defined logical name in the path java:comp/env/jdbc. The name definition in the deployment descriptor is relative to java:com/env, the environment of the bean. The resource factory is an object of the class javax.sql.DataSource. This class must be present on every EJB-conforming server that supports version 1.1 or 2.0/2.1. It is also a part of J2EE or available with the optional extension to JDBC 2.0. See Listing 4-14.

Listing 4-14: Schematic use of a reference to a JDBC database.

start example
javax.naming.Context beanCtx =
  new javax.naming.InitialContext();
 javax.sql.DataSource ds =
  (javax.sql.DataSource)
  beanCtx.lookup(
  "java:comp/env/jdbc/reference name");
java.sql.Connection con =
  ds.getConnection();
 
end example

Administered Objects

Since version 2.0 there has been the possibility of entering administered objects in the deployment descriptor. Administered objects are such items as JMS topics or JMS queues. If an enterprise bean uses JMS (Java Message Service) for a purpose such as sending information about the topic event topic, then it needs access to a topic factory and to the topic being addressed. The topic factory is a resource factory, and the topic is an administered object. Listing 4-15 shows how such an entry is to be made in the deployment descriptor. Chapter 6 deals extensively with this set of topics in relation to the Java message service and explains the meaning of the terms topic and topic factory and how these things are used.

Listing 4-15: Use of a reference to administered objects.

start example
...
<enterprise-beans>
  <session>
    ...
    <resource-ref>
      <description>
        description
      </description>
      <res-ref-name>
        jdbc/TopicFactory
      </res-ref-name>
      <res-type>
        javax.jms.TopicConnectionFactory
      </res-type>
      <res-auth>
        Container
      </res-auth>
    </resource-ref>
    <resource-env-ref>
      <resource-env-ref-name>
        jms/Event Topic
      </resource-env-ref-name>
      <resource-env-ref-type>
        javax.jms.Topic
      </resource-env-ref-type>
    </resource-env-ref>
  </session>
  ...
</enterprise-beans>
...
 
end example