Implementing the Stateful Session Bean

This section discusses the implementation of the remote home interface EnrollmentCartHome, the remote interface EnrollmentCart, and the stateful session bean class EnrollmentCartEJB.

Defining the Home Interface

Clients use home interface to create and remove session bean instances. Within the home interface, we define one or more create<method>(...) methods. The container tools generate the class that corresponds to this interface.

Note

A stateful session bean may have more than one create() methods, and some of them may have arguments. This is different, though, from the case of a stateless session bean, which can only have one create() method with no arguments.


Listing 6.1 shows the home interface EnrollmentCartHome.

Listing 6.1. The Full Text of day06/EnrollmentCartHome.java
package day06;

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

public interface EnrollmentCartHome extends EJBHome {
  EnrollmentCart create() throws CreateException, RemoteException;
}

The EnrollmentCartHome interface consists of a single create() method. To create the bean instance, a client calls the create() method of the home interface.

The throws clause of the create() method must include CreateException. This exception is thrown when there is a problem in creating or initializing the bean instance.

The remote home interface EnrollmentCartHome is a Java Remote Invocation Method (RMI) interface. So, the method arguments and return types of a remote method must be legal types for the RMI over Internet Inter-ORB Protocol (RMI/IIOP), such as primitives, serializable objects, and RMI/IIOP remote objects. Each method declared in the remote interface must include java.rmi.RemoteException in its throws clause. This exception is thrown when a remote invocation fails for some reason, such as network failure, protocol errors, and so on.

Defining the Remote Interface

This interface exposes a session bean's business methods to the client. The client calls the methods defined in the remote interface to invoke the business logic implemented by the bean. The container tools generate the class corresponding to this interface.

As shown in Listing 6.2, our EnrollmentCart interface defines three business methods: addCourses() for adding courses to the cart, getCourses() to get the currently selected courses, and empty() to clear the enrollment cart.

Listing 6.2. The Full Text of day06/EnrollmentCart.java
package day06;

import javax.ejb.*;
import java.rmi.RemoteException;
import java.util.Collection;

public interface EnrollmentCart extends EJBObject {
   public void addCourses(String[] courseIds) throws RemoteException;
   public Collection getCourses() throws RemoteException;
   public void empty() throws RemoteException;
}

The remote interface EnrollmentCart is a Java RMI interface. So, method arguments and return types of a remote method must be legal types for RMI/IIOP and the method must include java.rmi.RemoteException in its throws clause.

Implementing the Enterprise Bean Class

Listing 6.3 shows the EnrollmentCartEJB enterprise bean class.

Listing 6.3. The Full Text of day06/EnrollmentCartEJB.java
package day06;

import java.util.*;
import javax.ejb.*;
import javax.naming.*;

public class EnrollmentCartEJB implements SessionBean  {
      private SessionContext ctx;
      private HashSet cart;
      public EnrollmentCartEJB() {
         print("The container created this instance.
");
      }
      public void setSessionContext(SessionContext ctx) {
         print("The container called the setSessionContext method ");
         print("to associate session bean instance with its context.
");
         this.ctx = ctx;
      }

      public void ejbCreate() throws CreateException {
         print("The container called the ejbCreate method.
");
         cart = new HashSet();
      }
      public void ejbActivate() {
         print("This instance has just been reactivated.
");
      }
      public void ejbPassivate() {
         print("The container intends to passivate the instance.
");
      }
      public void ejbRemove() {
         print("This instance is in the process of being removed ");
         print("by the container.
");
      }
      public void addCourses(String[] courseIds) {
         print("The container called addCourses method.
");
         if ( courseIds == null) {
            return;
         }
         for ( int i = 0; i < courseIds.length ; i ++ ) {
            cart.add(courseIds[i]);
         }
      }
      public Collection getCourses() {
         print("The container called getCourses method.
");
         return cart;
      }
      public void empty() {
         print("The container called empty method.
");
         cart.clear();
      }
      void print(String s) {
         System.out.println(s);
      }
}

The stateful session bean implements the javax.ejb.SessionBean interface. The member variable cart constitutes the enterprise bean's conversational state. The bean implements the methods setSessionContext(), ejbCreate(), ejbActivate(), ejbPassivate(), and ejbRemove(), as defined in the javax.ejb.SessionBean interface. The ejbCreate() method initializes the bean instance. The bean class implements the business methods addCourses(), getCourses() and empty() defined in its remote interface.

Note

The EJB container serializes calls to each stateful session bean instance. This enables you to program a stateful bean as single-threaded, non-reentrant code. If two clients attempt to simultaneously access a session bean instance, the container throws an exception to the second client. The container throws java.rmi.RemoteException if the client is a remote client and javax.ejb.EJBException if the client is a local client.

The container does not serialize calls to a stateless session bean instance because the container routes each client request to a different instance of the session bean class.


Optional SessionSynchronization Interface

The SessionSynchronization interface, when implemented by the stateful session bean, allows the bean to be more transaction-aware. The container provides the bean with three callback methods: afterBegin(), beforeCompletion(), and afterCompletion(int). When the transaction begins, the container calls the afterBegin() method. The beforeCompletion() and afterCompletion(int) methods are used to manage resources before the transaction commits and aborts. We'll explore this interface on Day 16.

Declaring the Deployment Descriptors

Now it's time to create the deployment descriptors. We need to create two deployment descriptors before creating the bean's JAR file (in our case, day06_EnrollmentCart.jar), which is required to deploy the enrollment cart's stateful session bean into the WebLogic EJB container. These deployment descriptors are

  • Standard deployment descriptor ejb-jar.xml, as specified by Sun Microsystems, which is common to all EJBs

  • Vendor-specific deployment descriptor; WebLogic uses weblogic-ejb-jar.xml and JBoss uses jboss.xml

Declaring the Standard Deployment Descriptor ejb-jar.xml

This file is the standard descriptor as specified by Sun, and must contain the Sun Microsystems–specific EJB DTD.

The ejb-jar.xml describes the enterprise bean's deployment properties, such as its type and structure. As we learned on Day 2, this file provides the EJB container with information where it can find, and then load, the home interface, remote interface, and bean class. It declares its internal dependences and the application assembly information, which describes how the enterprise bean in the ejb-jar file (day06_EnrollmentCart.jar) is assembled into an application deployment unit.

Listing 6.4 shows the ejb-jar.xml file for the deployment descriptor of the EnrollmentCart EJB.

Listing 6.4. The Full Text of day06/ejb-jar.xml
<?xml version="1.0"?>

<!DOCTYPE ejb-jar PUBLIC
'-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'
'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>

<ejb-jar>
  <enterprise-beans>
    <session>
      <ejb-name>EnrollmentCart</ejb-name>
      <home>day06.EnrollmentCartHome</home>
      <remote>day06.EnrollmentCart</remote>
      <ejb-class>day06.EnrollmentCartEJB</ejb-class>
      <session-type>Stateful</session-type>
      <transaction-type>Container</transaction-type>
    </session>
  </enterprise-beans>
</ejb-jar>

The prolog contains the declaration and the DTD for the validation. The document root is the <ejb-jar> tag. It contains the structural information about all the included enterprise beans. The enterprise-beans element contains the declarations of one or more enterprise beans. The session element declares a session bean, and an ejb-name element within the session element defines the session bean's name (EnrollmentCart). The session element also declares other things such as the home interface (day06.EnrollmentCartHome), the remote interface (day06.EnrollmentCart), and the bean's class (day06.EnrollmentCartEJB). The session-type element declares that this is a stateful session bean.

The transaction-type element specifies that this bean uses container-managed transactions. Container-managed transactions are discussed in detail on Day 18.

Tip

The deployment descriptor element session-type is where the EJB container recognizes a stateful or stateless session bean.


Declaring the Vendor-Specific Deployment Descriptor

As you learned on Day 2, in addition to standard ejb-jar.xml, an application typically requires a certain amount of additional environment-specific or vendor-specific binding information, such as naming, security, and persistence. The following sections describe both the WebLogic and JBoss deployment descriptors.

Declaring the WebLogic Deployment Descriptor: weblogic-ejb-jar.xml

The weblogic-ejb-jar.xml file contains the WebLogic Server–specific EJB DTD that defines the naming, caching, clustering, and performance behavior of the deployed EJBs.

Listing 6.5 shows the weblogic-ejb-jar.xml deployment descriptor.

Listing 6.5. The Full Text of day06/weblogic-ejb-jar.xml
<?xml version="1.0"?>

<!DOCTYPE weblogic-ejb-jar PUBLIC
'-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN'
'http://www.bea.com/servers/wls700/dtd/weblogic-ejb-jar.dtd'>

<weblogic-ejb-jar>
  <weblogic-enterprise-bean>
    <ejb-name>EnrollmentCart</ejb-name>
         <stateful-session-descriptor>
           <stateful-session-cache>
              <max-beans-in-cache>5</max-beans-in-cache>
           </stateful-session-cache>
         </stateful-session-descriptor>
    <jndi-name>day06/EnrollmentCartHome</jndi-name>
  </weblogic-enterprise-bean>
</weblogic-ejb-jar>

The jndi-name element declares day06/EnrollmentCart as the JNDI name of the EnrollmentCart enterprise bean. The max-bean-in-cache element specifies the threshold at which WebLogic Server starts to passivate inactive instances in the instance cache to the back store. For demonstration purposes, we set the value to 5. As new concurrent clients request the bean's services, WebLogic Server creates new instances of the bean. When the sixth client requests the bean's services, the server passivates some of the idle beans, perhaps using the LRU (Least Recently Used) algorithm.

Declaring the JBoss Deployment Descriptor: jboss.xml

jboss.xml, the deployment descriptor that's specific to the JBoss server, defines the naming, caching, and other properties to control the behavior of the deployed EJBs. Listing 6.6 shows the jboss.xml file.

Listing 6.6. The Full Text of day06/jboss.xml
<?xml version="1.0" encoding="UTF-8"?>

<jboss>
  <enterprise-beans>
    <session>
      <ejb-name>EnrollmentCart</ejb-name>
      <jndi-name>day06/EnrollmentCartHome</jndi-name>
    </session>
  </enterprise-beans>

 <container-configurations>
  <container-configuration>
    <container-name>Standard Stateful SessionBean</container-name>
    <container-cache-conf>
     <cache-policy>
<![CDATA[org.jboss.ejb.plugins.LRUStatefulContextCachePolicy]]>
     </cache-policy>
        <cache-policy-conf>
             <max-capacity>100</max-capacity>
             <max-bean-age>2</max-bean-age>
             <overager-period>2</overager-period>
        </cache-policy-conf>
    </container-cache-conf>
  </container-configuration>
 </container-configurations>
</jboss>

In this deployment descriptor, the jndi-name element declares day06/EnrollmentCart as the JNDI name of the EnrollmentCart enterprise bean. The max-capacity element specifies the maximum capacity of the cache as 100. The element max-bean-age element specifies the maximum period of inactivity in seconds that a bean can have before it will be passivated by the container. The overager-period element specifies the period in seconds at which the container scans the cache for inactive beans and passivates them.

For demonstration purposes, we specify the container look for inactive beans every two seconds and the bean is considered inactive if it is not accessed for two seconds.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.105.215