Skip Headers

Oracle® Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide 10g Release 2 (10.1.2) Part No. B15505-02 |
| Library |  | Contents | Index

Previous | Next |

# 3 Implementing Session Beans

After you have installed Oracle Application Server Containers for J2EE (OC4J) and configured the base server and default Web site, you can start developing J2EE applications. This chapter assumes that you have a working familiarity with simple J2EE concepts and a basic understanding for EJB development.

The following subjects describe how to develop and deploy EJB applications with OC4J:

- Developing Session Beans—Developing and testing an EJB module within the standard J2EE specification.

- Prepare the EJB Application for Assembly—Before deploying, you must modify an XML file that acts as a manifest file for the enterprise application.

- Deploy the Enterprise Application to OC4J—Archive the enterprise Java application into an Enterprise ARchive (EAR) file and deploy it to OC4J.

- When Does Stateful Session Bean Passivation Occur?

This chapter demonstrates how to develop a stateless session bean. You can download the stateless session bean example from the OC4J sample code page at on the OTN Web site.

## Developing Session Beans

You develop EJB components for the OC4J environment in the same way as in any other standard J2EE environment. Here are the steps to develop EJBs:

1. Implement the Session Bean—Develop your EJB with its home interfaces, component interfaces, and bean implementation

2. Create the Deployment Descriptor—Create the standard J2EE EJB deployment descriptor for all beans in your EJB application.

3. Archive the EJB Application—Archive your EJB files into a JAR file.

### Implement the Session Bean

When you implement a session bean, create the following:

1. The home interfaces for the bean. The home interface defines the `create` method for your bean.

   1. The remote home interface extends `javax.ejb.EJBHome`.

   2. The local home interface extends `javax.ejb.EJBLocalHome`.

2. The component interfaces for the bean.

   1. The remote interface declares the methods that a client can invoke remotely. It extends `javax.ejb.EJBObject`.

   2. The local interface declares the methods that a collocated bean can invoke locally. It extends `javax.ejb.EJBLocalObject`.

3. The bean implementation includes the following:

   1. The implementation of the business methods that are declared in the component interfaces.

   2. The container callback methods that are inherited from the `javax.ejb.SessionBean`

   3. The `ejb*` methods that match the home interface `create` methods:

      - For stateless session beans, provide an `ejbCreate` method with no parameters.

      - For stateful session beans, provide an `ejbCreate` method with parameters matching those of the create method as defined in the home interfaces.

#### Creating the Home Interfaces

The home interfaces (remote and local) are used to create the bean instance; thus, they define the `create` method for your bean. The session bean can define the `create` method in the following ways:

EJB Type | Create Parameters
--- | ---
Stateless Session Bean | Can have only a single `create` method, with no parameters.
Stateful Session Bean | Can have one or more `create` methods, each with its own defined parameters.

For each `create` method, a corresponding `ejbCreate` method is defined in the bean implementation.

##### Remote Invocation

Any remote client invokes the EJB through its remote interface. The client invokes the `create` method that is declared within the remote home interface. The container passes the client call to the `ejbCreate` method—with the appropriate parameter signature—within the bean implementation. You can use the parameter arguments to initialize the state of the new EJB object.

1. The remote home interface must extend the `javax.ejb.EJBHome` interface.

2. All `create` methods may throw the following exceptions:

   - `javax.ejb.CreateException`

   - `javax.ejb.EJBException` or another `RuntimeException`

Example 3-1 Remote Home Interface for Session Bean

The following code sample illustrates a remote home interface for a stateless session bean called `HelloHome`.

    package hello;

    import javax.ejb.*;
    import java.rmi.*;

    public interface HelloHome extends EJBHome
    {
      public Hello create() throws CreateException, RemoteException;
    }

##### Local Invocation

An EJB can be called locally from a client that exists in the same container. Thus, a collocated bean, JSP, or servlet invokes the `create` method that is declared within the local home interface. The container passes the client call to the `ejbCreate` method—with the appropriate parameter signature—within the bean implementation. You can use the parameter arguments to initialize the state of the new EJB object.

1. The local home interface must extend the `javax.ejb.EJBLocalHome` interface.

2. All `create` methods may throw the following exceptions:

   - `javax.ejb.CreateException`

   - `javax.ejb.EJBException` or another `RuntimeException`

Example 3-2 Local Home Interface for Session Bean

The following code sample shows a local home interface for a stateless session bean called `HelloLocalHome`.

    package hello;

    import javax.ejb.*;

    public interface HelloLocalHome extends EJBLocalHome
    {
     public HelloLocal create() throws CreateException, EJBException;
    }

#### Creating the Component Interfaces

The component interfaces define the business methods of the bean that a client can invoke.

##### Creating the Remote Interface

The remote interface defines the business methods that a remote client can invoke. Here are the requirements for developing the remote interface:

1. The remote interface of the bean must extend the `javax.ejb.EJBObject` interface, and its methods must throw the `java.rmi.RemoteException` exception.

2. You must declare the remote interface and its methods as `public` for remote clients.

3. The remote interface, all its method parameters, and return types must be serializable. In general, any object that is passed between the client and the EJB must be serializable, because RMI marshals and unmarshals the object on both ends.

4. Any exception can be thrown to the client, as long as it is serializable. Runtime exceptions, including `EJBException` and `RemoteException`, are transferred back to the client as remote runtime exceptions.

Example 3-3 Remote Interface Example for Hello Session Bean

The following code sample shows a remote interface called `Hello` with its defined methods, each of which will be implemented in the stateless session bean.

    package hello;

    import javax.ejb.*;
    import java.rmi.*;

    public interface Hello extends EJBObject
    {
      public String sayHello(String myName) throws RemoteException;
    }

##### Creating the Local Interface

The local interface defines the business methods of the bean that a local (collocated) client can invoke.

1. The local interface of the bean must extend the `javax.ejb.EJBLocalObject` interface.

2. You declare the local interface and its methods as `public`.

Example 3-4 Local Interface for Hello Session Bean

The following code sample contains a local interface called `HelloLocal` with its defined methods, each of which will be implemented in the stateless session bean.

    package hello;

    import javax.ejb.*;

    public interface HelloLocal extends EJBLocalObject
    {
      public String sayHello(String myName) throws EJBException;
    }

#### Implementing the Bean

The bean contains the business logic for your application. It implements the following methods:

1. The signature for each of these methods must match the signature in the remote or local interface, except that the bean does not throw the `RemoteException`. Since both the local and the remote interfaces use the bean implementation, the bean implementation cannot throw the `RemoteException`.

2. The lifecycle methods are inherited from the `SessionBean` interface. These include the `ejb<Action>` methods, such as `ejbActivate`, `ejbPassivate`, and so on.

3. The `ejbCreate` methods that correspond to the `create` method(s) that are declared in the home interfaces. The container invokes the appropriate `ejbCreate` method when the client invokes the corresponding `create` method.

4. Any methods that are private to the bean or package used for facilitating the business logic. This includes private methods that your public methods use for completing the tasks requested of them.

Example 3-5 Hello Stateless Session Bean Implementation

The following code shows the bean implementation for the Hello example.

Note: You can download the stateless session bean example from the OC4J sample code page at `http://www.oracle.com/technology/tech/java/oc4j/demos/` on the OTN Web site.

    package hello;

    import javax.ejb.*;

    public class HelloBean implements SessionBean
    {
      public SessionContext ctx;

      public HelloBean()
      {    // constructor
      }

      public void ejbCreate() throws CreateException
      {   // when bean is created
      }

      public void ejbActivate()
      {    // when bean is activated
      }

      public void ejbPassivate()
      {    // when bean is deactivated
      }

      public void ejbRemove()
      {   // when bean is removed
      }

      public void setSessionContext(SessionContext ctx)
      {    this.ctx = ctx;
      }

      public void unsetSessionContext()
      {    this.ctx = null;
      }

      public String sayHello(String myName) throws EJBException
      {
        return ("Hello " + myName);
      }
    }

Note: You can download this example on OTN from the OC4J sample code page at `http://www.oracle.com/technology/tech/java/oc4j/demos/` on the OTN Web site.

### Create the Deployment Descriptor

After implementing and compiling your classes, you must create the standard J2EE EJB deployment descriptor for all beans in the module. The XML deployment descriptor (defined in the `ejb-jar.xml` file) describes the EJB module of the application. It describes the types of beans, their names, and attributes. The structure for this file is mandated in the DTD file, which is provided at " `http://java.sun.com/dtd/ejb-jar_2_0.dtd`".

Any EJB container services that you want to configure is also designated in the deployment descriptor. For information about data sources and JTA, see the Oracle Application Server Containers for J2EE Services Guide. For information about security, see the Oracle Application Server Containers for J2EE Security Guide.

After creation, place the deployment descriptors for the EJB application in the `META-INF` directory that is located in the same directory as the EJB classes. See Figure 3-1 for more information.

The following example shows the sections that are necessary for the `Hello` example, which implements both a remote and a local interface.

Example 3-6 XML Deployment Descriptor for Hello Bean

The following is the deployment descriptor for a version of the Hello example that uses a stateless session bean. This example defines both the local and remote interfaces. You do not have to define both interface types; you may define only one of them.

    <?xml version="1.0"?>
    <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">

    <ejb-jar>
       <display-name>hello</display-name>
       <description>
          An EJB app containing only one Stateless Session Bean
       </description>
       <enterprise-beans>
          <session>
             <description>no description</description>
             <display-name>HelloBean</display-name>
             <ejb-name>HelloBean</ejb-name>
             <home>hello.HelloHome</home>
             <remote>hello.Hello</remote>
             <local-home>hello.HelloLocalHome</local-home>
             <local>hello.HelloLocal</local>
             <ejb-class>hello.HelloBean</ejb-class>
             <session-type>Stateless</session-type>
             <transaction-type>Container</transaction-type>
          </session>
       </enterprise-beans>

       <assembly-descriptor>
          <container-transaction>
             <method>
                <ejb-name>HelloBean</ejb-name>
                <method-name>*</method-name>
             </method>
             <trans-attribute>Supports</trans-attribute>
          </container-transaction>
          <security-role>
             <role-name>users</role-name>
          </security-role>
       </assembly-descriptor>
    </ejb-jar>

Note: You can download this example on OTN from the OC4J sample code page at `http://www.oracle.com/technology/tech/java/oc4j/demos/` on the OTN Web site.

### Archive the EJB Application

After you have finalized your implementation and created the deployment descriptors, archive your EJB application into a JAR file. The JAR file should include all EJB application files and the deployment descriptor.

Note: If you have included a Web application as part of this enterprise Java application, follow the instructions for building the Web application in the Oracle Application Server Containers for J2EE User's Guide .

For example, to archive your compiled EJB class files and XML files for the `Hello` example into a JAR file, perform the following in the `../hello/ejb_module` directory:

    % jar cvf helloworld-ejb.jar .

This archives all files contained within the `ejb_module` subdirectory within the JAR file.

## Prepare the EJB Application for Assembly

To prepare the application for deployment, you do the following:

1. Modify the `application.xml` file with the modules of the enterprise Java application.

2. Archive all elements of the application into an EAR file.

These steps are described in the following sections:

- Modify the Application.XML File

- Create the EAR File

### Modify the Application.XML File

The `application.xml` file acts as the manifest file for the application and contains a list of the modules that are included within your enterprise application. You use each `<module>` element defined in the `application.xml` file to designate what comprises your enterprise application. Each module describes one of three things: EJB JAR, Web WAR, or any client files. Respectively, designate the `<ejb>`, `<web>`, and `<java>` elements in separate `<module>` elements.

- The `<ejb>` element specifies the EJB JAR filename.

- The `<web>` element specifies the Web WAR filename in the `<web-uri>` element, and its context in the `<context>` element.

- The `<java>` element specifies the client JAR filename, if any.

As Figure 3-1 shows, the `application.xml` file is located under a `META-INF` directory under the parent directory for the application. The JAR, WAR, and client JAR files should be contained within this directory. Because of this proximity, the `application.xml` file refers to the JAR and WAR files only by name and relative path—not by full directory path. If these files were located in subdirectories under the parent directory, then these subdirectories must be specified in addition to the filename.

Figure 3-1 Archive Directory Format

Description of the illustration primer3.gif

For example, the following example modifies the `<ejb>`, `<web>`, and `<java>` module elements within `application.xml` for the Hello EJB application that also contains a servlet that interacts with the EJB.

    <?xml version="1.0"?>
    <!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN" "http://java.sun.com/j2ee/dtds/application_1_2.dtd">
    <application>
      <display-name>helloworld j2ee application</display-name>
      <description>
         A sample J2EE application that uses a Helloworld Session Bean
         on the server and calls from java/servlet/JSP clients.
      </description>
      <module>
        <ejb>helloworld-ejb.jar</ejb>
      </module>
      <module>
        <web>
          <web-uri>helloworld-web.war</web-uri>
          <context-root>/helloworld</context-root>
        </web>
      </module>
      <module>
        <java>helloworld-client.jar</java>
      </module>
    </application>

### Create the EAR File

Create the EAR file that contains the JAR, WAR, and XML files for the application. Note that the `application.xml` file serves as the EAR manifest file.

To create the `helloworld.ear` file, execute the following in the `hello` directory contained in Figure 3-1:

    % jar cvf helloworld.ear .

This step archives the `application.xml`, the `helloworld-ejb.jar`, the `helloworld-web.war`, and the `helloworld-client.jar` files into the `helloworld.ear` file.

## Deploy the Enterprise Application to OC4J

After archiving your application into an EAR file, deploy the application to OC4J. See the Oracle Application Server Containers for J2EE User's Guide for information on how to deploy your application.

## 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.