Skip Headers

Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide 10g (9.0.4) Part Number B10324-01 |
Home | Contents | Index

# 9
Advanced EJB Subjects

This chapter discusses how to extend beyond the basics mentioned in each of the previous chapters.

Some of the EJB container services that you want to configure in the deployment descriptor are documented in other books. For information about data sources, JTA, JNDI, and RMI/IIOP, see the Oracle Application Server Containers for J2EE Services Guide. For information about security, including CSiV2, see the Oracle Application Server Containers for J2EE Security Guide.

This chapter covers the following subjects:

- Sharing Classes

- EJB Lifecycle Issues

- Techniques for Updating Persistence

- Entity Bean Concurrency and Database Isolation Modes

- Configuring Environment References

- Troubleshooting Common Errors

## Sharing Classes

If you want to share classes between EJBs, you can do one of the following:

- If two EJBs use the same classes, include all classes and the EJBs in the same JAR file. After deployment, both EJBs can use the common classes.

- Place the shared classes in its own JAR file in the application. Reference the shared JAR file in the `class-path` of the EJB JAR `manifest.mf` file, as follows:

      class-path:shared_classes.jar

  The location of the `shared_classes.jar` is relative to where the JAR that references is located in the EAR file. In this example, the `shared_classes.jar` file is at the same level as the EJB JAR.

- If all applications reference these classes, archive the shared classes in a JAR file and place this JAR file in the shared library directory of the default application. The `home/lib` is a default shared library. However, you can set shared library directories using Oracle Enterprise Manager in the General Properties page of the "default" application.

- If you want only certain applications to reference these classes, archive the shared classes in its own application, deploy the EAR for the application, and have the applications that reference the shared classes declare the shared classes application as its parent. The default parent in Oracle Application Server is the "default" application.

  The children see the namespace of its parent application. This is used in order to share services such as EJBs among multiple applications. See the Oracle Application Server Containers for J2EE User's Guide for directions on how to specify a parent application.

If you want to share classes between EJB and Web applications, you should place the referenced classes in a shared JAR.

If you receive a `ClassCastException`, then you probably have the following situation:

- You copied EJB interfaces into the WAR where the servlet resides for ease in development and forgot to delete them before creating the WAR file AND

- You turned on the `search_local_classes_first` attribute of the `<web-app-class-loader>` element in the `orion-web.xml` file.

To solve this problem, either eliminate the copied classes out of the WAR file or turn off the search_local_classes_first attribute. This attribute tells the class loader to load in the classes in the WAR file before loading in any other classes, including the classes within the EJB JAR file. For more information on this attribute, see the "Loading WAR File Classes Before System Classes in OC4J" section in the "Servlet Development" chapter of the Oracle Application Server Containers for J2EE Servlet Developer's Guide.

## EJB Lifecycle Issues

The following sections describe the EJB lifecycle issues in OC4J:

- When Does Stateful Session Bean Passivation Occur?

- Configuring Pool Sizes For Entity Beans

- Configuring Lazy Loading on CMP Entity Bean Finder Methods

### When Does Stateful Session Bean Passivation Occur?

Passivation enables the container to preserve the conversational state of an inactive idle bean instance by serializing the bean and its state into a secondary storage and removing it from memory. Before passivation, the container invokes the `ejbPassivate()` method enabling the bean developer to clean up held resources, such as database connections, TCP/IP sockets, or any resources that cannot be transparently passivated using object serialization. The object types that can be serialized and passivated are listed at the end of this section.

Note: OC4J passivates only stateful session beans. Stateless session beans have no state to passivate and entity beans should have their state saved within the database.

When a client invokes one of the methods of the passivated bean instance, the preserved conversational state data is activated, by de-serializing the bean from secondary storage and brought back into memory. Before activation, the container invokes the `ejbActivate()` method so that the bean developer can restore the resources released during `ejbPassivate()`. For more information on passivation, see the EJB specification.

Passivation is enabled by default. You can turn off passivation for stateful session beans by setting the `<sfsb-config>` element in the `server.xml` file to false. A stateful session bean can passivate only certain object types, as designated in "Object Types Enabled for Passivation". If you do not prepare your stateful session beans for passivation by releasing all resources and only allowing state to exist within the allowed object types, then passivation will fail everytime. If you do not want to change your object types and do not mind not passivating the object, you can disable passivation. In another case, you may want to disable passivation for performance reasons: passivation carries an overhead with it, and if you desire speed and are not really worried about resources, then you can turn passivation off.

An example of how to turn off passivation is as follows:

    <sfsb-config enable-passivation="false"/>

Note: See the `<sfsb-config>` element defined in the `server.xml` section of the Oracle Application Server Containers for J2EE User's Guide appendix for more information.

Passivation is invoked based on any combination of the following criteria:

- idle timeout expires

  You can set an idle timeout in seconds for each bean. When this timeout expires, passivation occurs. Set the `idletime` attribute in `<session-deployment>` to the appropriate number of seconds. Default: 300 seconds. (5 minutes). To disable, specify "never."

- out of resources

  Each of the following attributes in `<session-deployment>` define resource thresholds, when to check for those thresholds, and number of beans to passivate when the threshold is met.

  - `memory-threshold` - This attribute defines a threshold for how much used JVM memory is allowed before passivation should occur. Specify an integer that is translated as a percentage. When reached, beans are passivated, even if their idle timeout has not expired. Default: 80%. To disable, specify "never."

  - `max-instances-threshold` - This attribute defines a threshold for how many active beans exist in relation to the `max-instances` attribute definition. Specify an integer that is translated as a percentage. For example, if you define that the `max-instances` is 100 and the `max-instances-threshold` is 90%, then when the active bean instances reaches past 90, passivation of beans occurs. Default: 90%. To disable, specify "never."

  - `resource-check-interval` - The container checks all resources at this time interval. At this time, if any of the thresholds have been reached, passivation occurs. Default: 180 seconds (3 minutes). To disable, specify "never."

  - `passivate-count` - This attribute is an integer that defines the number of beans to be passivated if any of the resource thresholds have been reached. Passivation of beans is performed using the least recently used algorithm. Default: one-third of the `max-instances` attribute. You can disable this attribute by setting the count to zero or a negative number.

- The number of bean instances allowed is reached

  This number is set within the `<session-deployment>` `max-instances` attribute. The `max-instances` attribute controls the number of bean instances allowed in memory. When this value is reached, the container attempts to passivate the oldest bean instance from memory. If unsuccessful, the container waits the number of milliseconds set in the `call-timeout` attribute to see if a bean instance is removed from memory, either thru another passivation, calling the bean `remove()` method, or bean expiration, before a `TimeoutExpiredException` is thrown back to the client. Leave the `max-instances` value at zero to allow an infinite number of bean instances. Default is 0, which is infinite.

- OC4J instance termination

  All bean instances in the container's memory that are not passivated are serialized to the secondary storage. Upon OC4J start-up, these passivated beans are restored back to memory.

If the passivation serialization fails, then the container attempts to recover the bean back to memory as if nothing happened. No future passivation attempts will occur for any beans that fail passivation. Also, if activation fails, the bean and its references are completely removed from the container.

If new bean data is propagated to a passivated bean in a cluster, then the bean instance data is overwritten by the propagated data.

#### Object Types Enabled for Passivation

For serialization (during passivation) to the secondary storage to be successful, the conversational state of a bean must consist of only primitive values and the following special types:

- serializable objects

- null

- a reference to a component interface (`EJBObject` or `EJBLocalObject`)

- a reference to a home interface (`EJBHome` or `EJBLocalHome`)

- a reference to the `SessionContext` object

- a reference to the environment naming context

- a reference to the `UserTransaction` interface

- a reference to a resource manager connection factory

The bean developer is responsible for ensuring that all fields are of these types within the `ejbPassivate()` method. Any transient or non-serializable field should be set to null in this method.

#### Storage of Passivated EJBs

When OC4J passivates the stateful session bean, it is placed in the directory and filename designated by the `persistence-filename` attribute of the `<session-deployment>` element in the OC4J deployment descriptor. Passivation uses space within this directory to store the passivated beans. The default is the `application-deployments/persistence` directory. If passivation allocates large amounts of disk space, you may need to change the directory to a place on your system where you have the space available or turn off passivation.

### Configuring Pool Sizes For Entity Beans

You can set the minimum and maximum number of the bean instance pool, which contains EJB implementation instances that currently do not have assigned state. While the bean instance is in pool state, it is generic and can be assigned to a wrapper instance.

You can set the pool number with the following attributes of the `<entity-deployment>` element.

- The `max-instances` attribute sets the maximum entity bean instances to be allowed in the pool. An entity bean is set to a pooled state if not associated with a wrapper instance. Thus, it is generic.

  The default is 0, which means infinite. If you wanted to set the maximum bean implementation instances to 20, you would do as follows:

      <entity-deployment ...  max-instances="20"
       ...
      </entity-deployment>

- The `min-instances` attribute sets the minimum number allowed in the pool as follows:

      <entity-deployment ... min-instances="2"
       ...
      </entity-deployment>

### Configuring Lazy Loading on CMP Entity Bean Finder Methods

Each finder method retrieves one or more objects. In the default scenario (which is set to NO lazy loading), the finder method causes a single SQL select statement to be executed against the database. For a CMP bean, one or more objects are retrieved with all of their CMP fields. So, for example, with the `findAllEmployees` method, this finder retrieves all employee objects with all of the CMP fields in each employee object.

If you turn on lazy loading, then only the primary keys of the objects retrieved within the finder are returned. Then, only when you access the object within your implementation, the OC4J container uploads the actual object based on the primary key. With the `findAllEmployees` finder method example, all of the employee primary keys are returned in a `Collection`. The first time you access one of the employees in the `Collection`, OC4J uses the primary key to retrieve the single employee object from the database. You may want to turn on the lazy loading feature if the number of objects that you are retrieving is so large that loading them all into your local cache would be a performance degradation.

You have a performance consideration with lazy loading. If you retrieve multiple objects, but you only use a few of them, then you should turn on lazy loading. In addition, if you only use objects through the `getPrimaryKey` method, then you should also turn on lazy loading.

To turn on lazy loading in the `findByPrimaryKey` method, set the findByPrimaryKey-lazy-loading attribute to true, as follows:

    <entity-deployment ... findByPrimaryKey-lazy-loading="true" ... >

To turn on lazy loading in any custom finder method, set the lazy-loading attribute to true in the `<finder-method>` element for that custom finder, as follows:

    <finder-method ... lazy-loading="true" ...>
     ...
    </finder-method>

## Techniques for Updating Persistence

By default, the container persists only the modified fields in the bean. At the end of each call, a SQL command is created to update these fields. However, if you want to have all of your persistence fields updated, set the following attribute to false:

    <entity-deployment ...  update-changed-fields-only="false"
     ...
    </entity-deployment>

## Entity Bean Concurrency and Database Isolation Modes

In order to avoid resource contention and overwriting each others changes to database tables while allowing concurrent execution, entity bean concurrency and database isolation modes are provided.

- Database Isolation Modes

- Entity Bean Concurrency Modes

### Database Isolation Modes

The `java.sql.Connection` object represents a connection to a specific database. Database isolation modes are provided to define protection against resource contention. When two or more users try to update the same resource, a lost update can occur. That is, one user can overwrite the other user's data without realizing it. The `java.sql.Connection` standard provides four isolation modes, of which Oracle only supports two of these modes. These are as follows:

- `TRANSACTION_READ_COMMITTED`: Dirty reads are prevented; non-repeatable reads and phantom reads can occur. This level only prohibits a transaction from reading a row with uncommitted changes in it.

- `TRANSACTION_SERIALIZABLE`: Dirty reads, non-repeatable reads and phantom reads are prevented. This level includes the prohibitions in `TRANSACTION_REPEATABLE_READ` and further prohibits the situation where one transaction reads all rows that satisfy a WHERE condition, a second transaction inserts a row that satisfies that WHERE condition, and the first transaction rereads for the same condition, retrieving the additional "phantom" row in the second read.

  Note: You cannot set the isolation level to serializable if you are using a non-emulated data source. If you do, the non-emulated data source will not work.

You can configure one of these database isolation modes for a specific bean. That is, you can specify that when the bean starts a transaction, the database isolation mode for this bean be what is specified in the OC4J-specific deployment descriptor. Specify the isolation mode on what is important for the bean: parallel execution or data consistency. The isolation mode for this bean is set for the entire transaction.

The isolation mode can be set for each entity bean in the `isolation` attribute of the `<entity-deployment>` element. The values can be `committed` or `serializable`. The default is `committed`. To change it to `serializable`, configure the following in the `orion-ejb-jar.xml` for the intended bean:

    <entity-deployment ...  isolation="serializable"
     ...
    </entity-deployment>

There is always a trade-off between performance and data consistency. The `serializable` isolation mode provides data consistency; the `committed` isolation mode provides for parallel execution.

Note: There is a danger of lost updates with the `serializable` mode if the `max-tx-retries` element in the OC4J-specific deployment descriptor is greater than zero. The default for this value is zero. If this element is set to greater than zero, then the container retries the update if a second blocked client receives a `ORA-8177` exception. The retry would find the row unlocked and the update would occur. Thus, the second client's update succeeds and overwrites the first client's update. If you use `serializable`, you should consider leaving the `max-tx-retries` element as zero for data consistency.

If you do not set an isolation mode, you receive the mode that is configured in the database. Setting the isolation mode within the OC4J-specific deployment descriptor temporarily overrides the database configured isolation mode for the life of the global transaction for this bean. That is, if you define the bean to use the `serializable` mode, then the OC4J container will force the database to be `serializable` for this bean only until the end of the transaction.

### Entity Bean Concurrency Modes

OC4J also provides concurrency modes for handling resource contention and parallel execution within container-managed persistence (CMP) entity beans. Bean-managed persistence entity beans manage the resource locking within the bean implementation themselves. The concurrency modes configure when to block to manage resource contention or when to execute in parallel.

The concurrency modes are as follows:

- `PESSIMISTIC`: This manages resource contention and does not allow parallel execution. Only one user at a time is allowed to execute the entity bean at a single time.

- `OPTIMISTIC`: Multiple users can execute the entity bean in parallel. It does not monitor resource contention; thus, the burden of the data consistency is placed on the database isolation modes.

- `READ-ONLY`: Multiple users can execute the entity bean in parallel. The container does not allow any updates to the bean's state.

To enable the CMP entity bean concurrency mode, add the appropriate concurrency value of "`pessimistic`", "`optimistic`", or "`read-only`" to the `locking-mode` attribute of the `<entity-deployment>` element in the OC4J-specific deployment descriptor (`orion-ejb-jar.xml`). The default is "`optimistic`". To modify the concurrency mode to `pessimistic`, do the following:

    <entity-deployment ...  locking-mode="pessimistic"
     ...
    </entity-deployment>

These concurrency modes are defined per bean and the effects of locking apply on the transaction boundaries.

Parallel execution requires that the pool size for wrapper and bean instances are set correctly. For more information on how to configure the pool sizes, see "Configuring Environment References".

### Exclusive Write Access to the Database

The `exclusive-write-access` attribute of the `<entity-deployment>` element states that this is the only bean that accesses its table in the database and that no external methods are used to update the resource. It informs the OC4J instance that any cache maintained for this bean will only be dirtied by this bean. Essentially, if you set this attribute to true, you are assuring the container that this is the only bean that will update the tables used within this bean. Thus, any cache maintained for the bean does not need to constantly update from the back-end database.

This flag does not prevent you from updating the table; that is, it does not actually lock the table. However, if you update the table from another bean or manually, the results are not automatically updated within this bean.

The default for this attribute is false. Because of the effects of the entity bean concurrency modes, this element is only allowed to be set to true for a `read-only` entity bean. OC4J will always reset this attribute to false for `pessimistic` and `optimistic` concurrency modes.

    <entity-deployment ...  exclusive-write-access="true"
     ...
    </entity-deployment>

### Effects of the Combination of the Database Isolation and Bean Concurrency Modes

For the `pessimistic` and `read-only` concurrency modes, the setting of the database isolation mode does not matter. These isolation modes only matter if an external source is modifying the database.

If you choose `optimistic` with `committed`, you have the potential to lose an update. If you choose `optimistic` with `serializable`, you will never lose an update. Thus, your data will always be consistent. However, you can receive an `ORA-8177` exception as a resource contention error.

#### Differences Between Pessimistic and Optimistic/Serializable

An entity bean with the `pessimistic` concurrency mode does not allow multiple clients to execute a bean (either on the same or on different instances of the same primary key). Only one client is allowed to execute the instance at any one moment.

An entity bean with the `optimistic` concurrency mode allows multiple instances of the bean implementation to execute in parallel. However, it could result in potential lost updates (and conflicts), because two different transactions may update the same row simultaneously.

Setting the transaction isolation mode to `serializable` allows the detection of conflicts when they occur. At that moment, the update from one of the transactions raises a `SQLException` and that transaction is rolled back.

Optionally, you may set the `tx-retries` attribute of the `<entity-deployment>` element to a value more than one, so that the transaction is retried.

### Affects of Concurrency Modes on Clustering

All concurrency modes behave in a similar manner whether they are used within a standalone or a clustered environment. This is because the concurrency modes are locked at the database level. Thus, even if a pessimistic bean instance is clustered across nodes, the moment one instance tries to execute, the database locks out all other instances.

## Configuring Environment References

You can create three types of environment elements that are accessible to your bean during runtime: environment variables, EJB references, and resource managers. These environment elements are static and can not be changed by the bean.

ISVs typically develop EJBs that are independent from the EJB container. In order to distance the bean implementation from the container specifics, you can create environment elements that map to one of the following: defined variables, entity beans, or resource managers. This indirection enables the bean developer to refer to existing variables, EJBs, and a JDBC `DataSource` without specifying the actual name. These names are defined in the deployment descriptor and are linked to the actual names within the OC4J-specific deployment descriptor.

### Environment variables

You can create environment variables that your bean accesses through a lookup on the `InitialContext`. These variables are defined within an `<env-entry>` element and can be of the following types: `String`, `Integer`, `Boolean`, `Double`, `Byte`, `Short`, `Long`, and `Float`. The name of the environment variable is defined within `<env-entry-name>`, the type is defined in `<env-entry-type>`, and its initialized value is defined in `<env-entry-value>`. The `<env-entry-name>` is relative to the "`java:comp/env"` context.

For example, the following two environment variables are declared within the XML deployment descriptor for `java:comp/env/minBalance` and `java:comp/env/maxCreditBalance`.

    <env-entry>
         <env-entry-name>minBalance</env-entry-name>
         <env-entry-type>java.lang.Integer</env-entry-type>
         <env-entry-value>500</env-entry-value>
    </env-entry>
    <env-entry>
         <env-entry-name>maxCreditBalance</env-entry-name>
         <env-entry-type>java.lang.Integer</env-entry-type>
         <env-entry-value>10000</env-entry-value>
    </env-entry>

Within the bean's code, you would access these environment variables through the `InitialContext`, as follows:

    InitialContext ic = new InitialContext();
    Integer min = (Integer) ic.lookup("java:comp/env/minBalance");
    Integer max = (Integer) ic.lookup("java:comp/env/maxCreditBalance"));

Notice that to retrieve the values of the environment variables, you prefix each environment element with "`java:comp/env/`", which is the location that the container stored the environment variable.

If you wanted the value of the environment variable to be defined in the OC4J-specific deployment descriptor, you can map the `<env-entry-name>` to the `<env-entry-mapping>` element in the OC4J-specific deployment descriptor. This means that the value specified in the `orion-ejb-jar.xml` file overrides any value that may be specified in the `ejb-jar.xml` file. The type specified in the EJB deployment descriptor stays the same.

Figure 9-1 shows how the `minBalance` environment variable is defined as 500 within the OC4J-specific deployment descriptor.

#### Figure 9-1 Environment Variable Mapping

Text description of the illustration o_1047.gif

### Environment References To Other Enterprise JavaBeans

You can define an environment reference to an EJB through either its local or remote interface within the deployment descriptor. If your bean calls out to another bean, you can enable your bean to invoke the second bean using a reference defined within the deployment descriptors. You create a logical name within the EJB deployment descriptor, which is mapped to the concrete name of the bean within the OC4J-specific deployment descriptor.

Declaring the target bean as an environment reference provides a level of indirection: the originating bean can refer to the target bean with a logical name.

A reference to the local interface of a bean is defined in an `<ejb-local-ref>` element; a reference to the remote interface of a bean is defined in an `<ejb-ref>` element.

To define a reference to another EJB within the JAR or in a bean declared as a parent, you provide the following:

1. Name--provide a name for the target bean. This name is what the bean uses within the JNDI location for accessing the target bean. The name should begin with "`ejb/`", such as "`ejb/myEmployee`", and will be available within the "`java:comp/env/ejb`" context.

   - This name can be the actual name of the bean; that is, the name defined within the `<ejb-name>` element in the `<session>` or `<entity>` elements.

   - This name can be a logical name that you want to use in your implementation. But it is not the actual name of the bean. If you use a logical name, the actual name must either be specified in the `<ejb-link>` element or `<ejb-ref-mapping>` element in the OC4J-specific deployment descriptor.

2. Type--define whether the bean is a session or an entity bean. Value should be either "`Session`" or "`Entity`".

3. Home--provide the fully qualified home interface name.

4. Remote--provide the fully qualified remote interface name.

5. Link--provide the EJB name of the target bean. This is optional and only used if you used a logical name in the `name` attribute.

#### Examples of References to a Local Interface

If you have two beans in the JAR: `BeanA` and `BeanB`. If `BeanB` creates a reference to the local interface of `BeanA`, you can define this reference in one of three methods:

- Provide the actual name of the bean. `BeanB` would define the following `<ejb-local-ref>` within its definition:

      <ejb-local-ref>
       <ejb-ref-name>myBeans/BeanA</ejb-ref-name>
       <ejb-ref-type>Session</ejb-ref-type>
       <local-home>myBeans.BeanALocalHome</local-home>
       <local>myBeans.BeanALocal</local>
      </ejb-local-ref>

  Since the EJB name of the target is specified in the `<ejb-ref-name>` element, no `<ejb-link>` is necessary for this method. However, the `BeanB` implementation must refer to `BeanA` in the JNDI retrieval, which would use `java:comp/env/myBeans/BeanA` for retrieval within an EJB or Java client and use "`myBeans/BeanA`" within a servlet.

  Note: Servlets do not require the prefix of "`java:comp/env`" in the JNDI lookup. Thus, they will always either reference just the actual JNDI name or the logical name of the EJB.

- Provide the EJB name of the bean in the `<ejb-link>` element. You can use any logical name in your bean implementation for the JNDI retrieval by defining a logical name in the `<ejb-ref-name>` element and then map it to the target bean by specifying the target EJB name in the `<ejb-link>` element. The following defines a logical name of `ejb/nextVal` that this bean can use in its code in the JNDI retrieval. The container maps it to the target bean, `myBeans/BeanA`, which is specified in the `<ejb-link>` element.

      <ejb-local-ref>
       <ejb-ref-name>ejb/nextVal</ejb-ref-name>
       <ejb-ref-type>Session</ejb-ref-type>
       <local-home>myBeans.BeanALocalHome</local-home>
       <local>myBeans.BeanALocal</local>
       <ejb-link>myBeans/BeanA</ejb-link>
      </ejb-local-ref>

  `BeanB` would use `java:comp/env/ejb/nextVal` in the JNDI retrieval of `BeanA`.

- Provide the logical name of the bean in the `<ejb-ref-name>` and the actual name of the bean in the `<ejb-ref-mapping>` element in the OC4J-specific deployment descriptor.

  The reference in the EJB deployment descriptor would be as follows:

      <ejb-local-ref>
       <ejb-ref-name>ejb/nextVal</ejb-ref-name>
       <ejb-ref-type>Session</ejb-ref-type>
       <local-home>myBeans.BeanALocalHome</local-home>
       <local>myBeans.BeanALocal</local>
      </ejb-local-ref>

  The "`ejb/nextVal`" logical name is mapped to an actual name in the OC4J-deployment descriptor as follows:

      <ejb-ref-mapping name="ejb/nextVal" location="myBeans/BeanA"/>

  `BeanB` would use `java:comp/env/ejb/nextVal` in the JNDI retrieval of `BeanA`.

  As shown in Figure 9-2, the logical name for the bean is mapped to the JNDI name by providing the same name, "`ejb/nextVal`", in both the `<ejb-ref-name>` in the EJB deployment descriptor and the `name` attribute within the `<ejb-ref-mapping>` element in the OC4J-specific deployment descriptor.

  #### Figure 9-2 EJB Reference Mapping

  Text description of the illustration o_1048.gif

  #### Accessing EJBs Using Environment References

  To access a bean from within your implementation using a reference, use the <`ejb-ref-name`> defined in the EJB deployment descriptor in the JNDI lookup.

  If you are using the default context when you retrieve the `InitialContext`, then you can do one of the following:

  - Prefix the logical name defined within the `<ejb-ref-name>` element with "`java:comp/env/ejb/`", which is where the container places the EJB references defined in the deployment descriptor.

  - Do not prefix the logical name with any string and supply only the logical name defined in the `<ejb-ref-name>`.

  The following is a lookup from an EJB client, using the `java:comp/env` prefix, assuming that the logical name is "`ejb/HelloWorld`."

      InitialContext ic = new InitialContext();
      HelloHome hh = (HelloHome)ic.lookup("java:comp/env/ejb/HelloWorld");

  The following is a lookup using only the logical name of "`ejb/HelloWorld`."

      InitialContext ic = new InitialContext();
      HelloHome hh = (HelloHome)ic.lookup("ejb/HelloWorld");

  However, if you are not using the default context, but are specifically using another context, such as the `RMIInitialContext` object, you can only use the logical name, as follows:

      InitialContext ic = new InitialContext();
      HelloHome hh = (HelloHome)ic.lookup("ejb/HelloWorld");

  #### Example 9-1 Defining a Local EJB Reference Within the Environment

  The following example defines a reference to the local interface of the `Hello` bean, as follows:

  1. The logical name used for the target bean within the originating bean is "`java:comp/env/ejb/HelloWorld`".

  2. The target bean is a session bean.

  3. Its local home interface is `hello.HelloLocalHome`; its local interface is `hello.HelloLocal`.

  4. The `<ejb-ref-name>` attribute is the logical name used within the originating bean. This is optional. In this example, this bean is defined in the EJB deployment descriptor under the "`ejb/HelloWorld`" name.

     Text description of the illustration o_1051.gif

  The `<ejb-ref-name>` element in the EJB deployment descriptor is mapped to the `name` attribute within the `<ejb-ref-mapping>` element in the OC4J-specific deployment descriptor by providing the same logical name in both elements. The Oracle-specific deployment descriptor would have the following definition to map the logical bean name of "`java:comp/env/ejb/HelloWorld`" to the JNDI location "`/test/myHello`".

  Text description of the illustration advance5.gif

  To invoke this bean from within your implementation, you use the <`ejb-ref-name`> defined in the EJB deployment descriptor. In EJB or pure Java clients, you prefix this name with "`java:comp/env/ejb/`", which is where the container places the EJB references defined in the deployment descriptor. Servlets only require the logical name defined in the `<ejb-ref-name>`.

  The following is a lookup from an EJB, acting as a client:

      InitialContext ic = new InitialContext();
      HelloHome hh = (HelloHome)ic.lookup("java:comp/env/ejb/HelloWorld");

  Alternatively, you could lookup the name, as follows:

      InitialContext ic = new InitialContext();
      HelloHome hh = (HelloHome)ic.lookup("ejb/HelloWorld");

  #### Examples of References to a Remote Interface

  Defining a reference to a remote interface uses exactly the same rules as the local interface, as described in "Examples of References to a Local Interface". The only difference is as follows:

  - Use the `<ejb-ref>` instead of the `<ejb-local-ref>` element.

  - Use the `<home>` and `<remote>` elements instead of the `<local-home>` and `<local>` elements.

  Everything else is the same.

  The following uses an example with two beans in the JAR: `BeanA` and `BeanB`. If `BeanB` creates a reference to `BeanA`, you can define this reference in one of three methods:

  - Provide the actual name of the bean.

        <ejb-ref>
         <ejb-ref-name>myBeans/BeanA</ejb-ref-name>
         <ejb-ref-type>Session</ejb-ref-type>
         <home>myBeans.BeanAHome</home>
         <remote>myBeans.BeanA</remote>
        </ejb-ref>

  - Provide the EJB name of the bean in the `<ejb-link>` element.

        <ejb-ref>
         <ejb-ref-name>ejb/nextVal</ejb-ref-name>
         <ejb-ref-type>Session</ejb-ref-type>
         <home>myBeans.BeanAHome</home>
         <remote>myBeans.BeanA</remote>
         <ejb-link>myBeans/BeanA</ejb-link>
        </ejb-ref>

  - Provide the logical name of the bean in the `<ejb-ref-name>` and the actual name of the bean in the `<ejb-ref-mapping>` element in the OC4J-specific deployment descriptor.

        <ejb-ref>
         <ejb-ref-name>ejb/nextVal</ejb-ref-name>
         <ejb-ref-type>Session</ejb-ref-type>
         <home>myBeans.BeanAHome</home>
         <remote>myBeans.BeanA</remote>
        </ejb-ref>

    The "`ejb/nextVal`" logical name is mapped to an actual name in the OC4J-deployment descriptor as follows:

        <ejb-ref-mapping name="ejb/nextVal" location="myBeans/BeanA"/>

  Refer to "Examples of References to a Local Interface" for more description and a code example.

  ### Environment References To Resource Manager Connection Factory References

  The resource manager connection factory references can include resource managers such as JMS, Java mail, URL, and JDBC `DataSource` objects. Similar to the EJB references, you can access these objects from JNDI by creating an environment element for each object reference. However, these references can only be used for retrieving the object within the bean that defines these references. Each is fully described in the following sections:

  - JDBC DataSource

  - Mail Session

  - URL

  #### JDBC DataSource

  You can access a database through JDBC either using the traditional method or by creating an environment element for a JDBC `DataSource`. In order to create an environment element for your JDBC `DataSource`, you must do the following:

  1. Define the `DataSource` in the `data-sources.xml` file.

  2. Create a logical name within the `<res-ref-name>` element in the EJB deployment descriptor. This name should always start with "`jdbc`". In the bean code, the lookup of this reference is always prefaced by "`java:comp/env/jdbc`".

  3. Map the logical name within the EJB deployment descriptor to the JNDI name, created in step 1, within the OC4J-specific deployment descriptor.

  4. Lookup the object reference within the bean with the "`java:comp/env/jdbc`" preface and the logical name defined in the EJB deployment descriptor.

  As shown in Figure 9-3, the JDBC `DataSource` uses the JNDI name "`test/OrderDataSource`". The logical name that the bean knows this resource as is "`jdbc/OrderDB`". These names are mapped together within the OC4J-specific deployment descriptor. Thus, within the bean's implementation, the bean can retrieve the connection to `OrderDataSource` by using the "`java:comp/env/jdbc/OrderDB`" environment element.

  #### Figure 9-3 JDBC Resource Manager Mapping

  Text description of the illustration o_1049.gif

  #### Example 9-2 Defining an environment element for JDBC Connection

  The environment element is defined within the EJB deployment descriptor by providing the logical name, "`jdbc/OrderDB`", its type of `javax.sql.DataSource`, and the authenticator of "`Application`".

  Text description of the illustration advance8.gif

  The environment element of "`jdbc/OrderDB`" is mapped to the JNDI bound name for the connection, "`test/OrderDataSource`" within the Oracle-specific deployment descriptor.

  Text description of the illustration advance9.gif

  Once deployed, the bean can retrieve the JDBC `DataSource` as follows:

      javax.sql.DataSource db;
      java.sql.Connection conn;
      .
      .
      .
      db = (javax.sql.DataSource)
      initCtx.lookup("java:comp/env/jdbc/OrderDB");
      conn = db.getConnection();

  Note: This example assumes that a `DataSource` is specified in the `data-sources.xml` file with the JNDI name of "`/test/OrderDataSource`".

  #### Mail Session

  You can create an environment element for a Java mail `Session` object through the following:

  1. Bind the `javax.mail.Session` reference within the JNDI name space in the `application.xml` file using the `<mail-session>` element, as follows:

         <mail-session location="mail/MailSession"
            smtp-host="mysmtp.oraclecorp.com">
            <property name="mail.transport.protocol" value="smtp"/>
            <property name="mail.smtp.from" value="emailaddress@oracle.com"/>
         </mail-session>

  The location attribute contains the JNDI name specified in the location attribute of the `<resource-ref-mapping>` element in the OC4J-specific deployment descriptor.

  1. Create a logical name within the `<res-ref-name>` element in the EJB deployment descriptor. This name should always start with "`mail`". In the bean code, the lookup of this reference is always prefaced by "`java:comp/env/mail`".

  2. Map the logical name within the EJB deployment descriptor to the JNDI name, created in step 1, within the OC4J-specific deployment descriptor.

  3. Lookup the object reference within the bean with the "`java:comp/env/mail`" preface and the logical name defined in the EJB deployment descriptor.

  As shown in Figure 9-4, the `Session` object was bound to the JNDI name "`/test/myMailSession`". The logical name that the bean knows this resource as is "`mail/testMailSession`". These names are mapped together within the OC4J-specific deployment descriptor. Thus, within the bean's implementation, the bean can retrieve the connection to the bound `Session` object by using the "`java:comp/env/mail/testMailSession`" environment element.

  #### Figure 9-4 Session Resource Manager Mapping

  Text description of the illustration o_1050.gif

  This environment element is defined with the following information:

  Element | Description
  --- | ---
  `<res-ref-name>` | The logical name of the `Session` object to be used within the originating bean. The name should be prefixed with "`mail`/". In our example, the logical name for our mail session is "`mail/testMailSession`".
  `<res-type>` | The Java type of the resource. For the Java mail `Session` object, this is `javax.mail.Session`.
  `<res-auth>` | Define who is responsible for signing on to the database. The value can be "`Application`" or "`Container`" based on who provides the authentication information.

  #### Example 9-3 Defining an environment element for Java mail Session

  The environment element is defined within the EJB deployment descriptor by providing the logical name, "`mail/testMailSession`", its type of `javax.mail.Session`, and the authenticator of "`Application`".

  Text description of the illustration advanc10.gif

  The environment element of "`mail/testMailSession`" is mapped to the JNDI bound name for the connection, "`test/myMailSession`" within the OC4J-specific deployment descriptor.

  Text description of the illustration advanc11.gif

  Once deployed, the bean can retrieve the `Session` object reference as follows:

      InitialContext ic = new InitialContext();
      Session session = (Session)
      ic.lookup("java:comp/env/mail/testMailSession");

      //The following uses the mail session object
      //Create a message object
      MimeMessage msg = new MimeMessage(session);

      //Construct an address array
      String mailTo = "whosit@oracle.com";
      InternetAddress addr = new InternetAddress(mailto);
      InternetAddress addrs[] = new InternetAddress[1];
      addrs[0] = addr;

      //set the message parameters
      msg.setRecipients(Message.RecipientType.TO, addrs);
      msg.setSubject("testSend()" + new Date());
      msg.setContent(msgText, "text/plain");

      //send the mail message
      Transport.send(msg);

  #### URL

  You can create an environment element for a Java `URL` object through the following:

  1. Create a logical name within the `<res-ref-name>` element in the EJB deployment descriptor. This name should always start with "`url`". In the bean code, the lookup of this reference is always prefaced by "`java:comp/env/url`".

  2. Map the logical name within the EJB deployment descriptor to the URL within the OC4J-specific deployment descriptor.

  3. Lookup the object reference within the bean with the "`java:comp/env/url`" preface and the logical name defined in the EJB deployment descriptor.

  As shown in Figure 9-5, the `URL` object was bound to the URL "`http://www.myURL`.`com`". The logical name that the bean knows this resource as is "`url/testURL`". These names are mapped together within the OC4J-specific deployment descriptor. Thus, within the bean's implementation, the bean can retrieve a reference to the URL object by using the "`java:comp/env/url/testURL`" environment element.

  #### Figure 9-5 URL Resource Manager Mapping

  Text description of the illustration o_1051.gif

  This environment element is defined with the following information:

  Element | Description
  --- | ---
  `<res-ref-name>` | The logical name of the `URL` object to be used within the originating bean. The name should be prefixed with "`url`/". In our example, the logical name for our URL is "`url/testURL`".
  `<res-type>` | The Java type of the resource. For the Java URL object, this is `java.net.URL`.
  `<res-auth>` | Define who is responsible for signing on to the database. At this time, the only value supported is "`Application`". The application provides the authentication information.

  #### Example 9-4 Defining an Environment Element for a URL

  The environment element is defined within the EJB deployment descriptor by providing the logical name, "`url/testURL`", its type of `java.net.URL`, and the authenticator of "`Application`".

  Text description of the illustration advanc12.gif

  The environment element of "`url/testURL`" is mapped to the URL "`http://www.myURL.com`" within the OC4J-specific deployment descriptor.

  Text description of the illustration advanc13.gif

  Once deployed, the bean can retrieve the `URL` object reference as follows:

      InitialContext ic = new InitialContext();
      URL url = (URL) ic.lookup("java:comp/env/url/testURL");

      //The following uses the URL object
      URLConection conn = url.openConnection();

  ## Troubleshooting Common Errors

  The following are common errors that may occur when executing EJBs:

  - Out Of Memory Error During Deployment

  - Out of Memory During Execution

  - NamingException Thrown

  - Deadlock Conditions

  - ClassCastException

  - NullPointerException Thrown From Remote EJB

  ### Out Of Memory Error During Deployment

  If the deployment process is interrupted for any reason, you may need to clean up the temp directory, which by default is `/var/tmp`, on your system. The deployment wizard uses 20 MB in swap space of the temp directory for storing information during the deployment process. At completion, the deployment wizard cleans up the temp directory of its additional files. However, if the wizard is interrupted, it may not have the time or opportunity to clean up the temp directory. Thus, you must clean up any additional deployment files from this directory yourself. If you do not, this directory may fill up, which will disable any further deployment. If you receive an `Out` `of` `Memory` error, check for space available in the temp directory.

  To change the temp directory, set the command-line option for the OC4J process to `java.io.tmpdir=<new_tmp_dir>`. You can set this command-line option in the Server Properties page. Drill down to the OC4J Home Page. Scroll down to the Administration Section. Select Server Properties. On this page, Scroll down to the Command Line Options section and add the `java.io.tmpdir` variable definition to the OC4J Options line. All new OC4J processes will start with this property.

  ### Out of Memory During Execution

  If you see that the OC4J memory is growing consistently while executing, then you may have invalid symbolic links in your `application.xml` file. OC4J loads all resources using the links in the `application.xml` file. If these links are invalid, then the C heap continues to grow causing OC4J to run out of memory. Ensure that all symbolic links are valid and restart OC4J.

  In addition, keep the number of JAR files to a minimum in the in the directories where the symbolic links point. Eliminate all unused JARs from these directories. OC4J searches all JARs for classes and resources; thus, taking time and memory consumption by the file cache, as well as being mapped into the address space.

  ### NamingException Thrown

  If you are trying to remotely access an EJB and you receive an `javax.naming.NamingException` error, your JNDI properties are probably not initialized properly. See "Setting JNDI Properties" for a discussion on setting up JNDI properties when accessing an EJB from a remote object or remote servlet.

  ### Deadlock Conditions

  If the call sequence of several beans cause a deadlock scenario, the OC4J container notices the deadlock condition and throws a Remote exception that details the deadlock condition in one of the offending beans.

  ### ClassCastException

  When you have an EJB or Web application that references other shared EJB classes, you should place the referenced classes in a shared JAR. In certain situations, if you copy the shared EJB classes into WAR file or another application that references them, you may receive a `ClassCastException` because of a class loader issue. To be completely safe, never copy referenced EJB classes into the WAR file of its application or into another application.

  See "Sharing Classes" for more information.

  ### NullPointerException Thrown From Remote EJB

  When accessing a remote EJB from a Web application, you receive the following error: "`java.lang.NullPointerException: domain was null` ". In this case, you must set an environment property in your client while accessing the EJB set `dedicated.rmicontext` to true.

  The following demonstrates how to use this additional environment property:

      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,

      	"com.evermind.server.rmi.RMIInitialContextFactory");
      env.put(Context.SECURITY_PRINCIPAL, "admin");
      env.put(Context.SECURITY_CREDENTIALS, "admin");
      env.put(Context.PROVIDER_URL, "ormi://myhost-us/ejbsamples");
      env.put("dedicated.rmicontext","true"); // for 9.0.2.1 and above
      Context context = new InitialContext(env);

  See "Load Balancing Options" for more information on `dedicated.rmicontext`.

| Copyright © 2002, 2003 Oracle Corporation. All Rights Reserved. |
Home | Contents | Index