C H A P T E R  3

Developing Session Beans

You can use the EJB Builder in the Sun ONE Studio 5 IDE to program the session beans that perform server-side business logic on behalf of clients in your Enterprise JavaBeans application. This chapter discusses the process of creating and working with stateless and stateful session beans.

A session bean of either type can use the EJB container to manage transactions, or you can code a session bean to manage its own transactions. Session beans access persistent data using the JDBC API and the Java Transaction API (JTA). A session bean can manage one or more entity beans.

The IDE provides wizards that help you create the parts of an enterprise bean: a bean class and its two (or four) interfaces. The default is a remote interface and a home interface, but you can substitute or add a local interface and a local home interface. The task of creating the session bean's infrastructure is automated for you.

When you're programming session beans, you have many options in addition to those described in this chapter. Although the Sun ONE Studio 5 IDE is designed to take care of much of your coding work, the IDE also supports those options flexibly and leaves many decisions up to you. For detailed instructions in coding session beans, refer to the resources listed in Before You Read This Book, or to one of the many excellent texts on programming enterprise beans.


Using the EJB Builder With Session Beans

The EJB Builder is a collection of wizards, property sheets, and editors with which you can build enterprise beans consistently and easily. The EJB Builder is installed automatically with the IDE and becomes visible when you choose File right arrow New from the main window or New right arrow All Templates from the contextual menu in the Explorer's Filesystems tab.

You can take several approaches to creating your session beans in the IDE. However, you get the most comprehensive support and, in general, the fastest path to bean completion, if you use the approach recommended in this chapter. You can also use the example applications and tutorials, available from the main window's Help right arrow Learning menu, to explore different ways of creating enterprise beans. The methodology described in these documents takes full advantage of the IDE's ability to ensure consistency and its adherence to the J2EE standard.

For best results, use the EJB Builder to program session beans by:

The logical node is the best place from which to work with a session bean. All logical nodes appear in the Explorer with this icon:Logical node icon.

From a session bean's logical node, you can add a business method that is automatically placed in the bean class and the appropriate interfaces, validate the entire bean, build a test application for the bean, and create an EJB module around the bean for production purposes.


Selecting a Session Bean Type

A session bean handles interaction between a client and an application service; the duration of this interaction is the session. Should your session bean be stateful or stateless? Should it manage its own transactions or have its container manage them? All of these choices are discussed next.

The EJB Builder is designed to support all of these choices, and you use the same wizard to generate the session bean's infrastructure. Later, you finish specifying each type of session bean.

Details follow in these sections:

Stateless or Stateful Session Beans

The main purpose of a session bean is to perform work on behalf of a client application, that is, to help a client carry on a conversation with one or more entity beans on the server side. When such a conversation consists of more than a simple question and a simple answer, the conversation's manager (that is, the session bean) must remember certain information until the conversation is finished. In that case, the session bean must have state. A stateless session bean might manage a less complex conversation.

A more detailed discussion of this choice is in Chapter 2. TABLE 3-1 highlights the design considerations.

TABLE 3-1 Deciding Between Stateless and Stateful Session Beans

Issue

Stateless

Stateful

Scope

A stateless session bean manages a simple interaction between a client and an entity, and calls only one method per session.

A stateful session bean manages a more complex interaction between a client and an entity, and calls more than one method per session.

Initialization

A stateless bean carries no data that must be initialized.

A stateful bean's state must be initialized. For example, if the bean is designed to set up access to remote resources, it acquires a reference to a resource factory.

Information saved

During its session, a stateless bean saves no state information between method invocations.

During its session, a stateful bean maintains a conversational state between the client and server. It saves state information between method invocations but discards the information when the session ends.

Relationship with clients

A stateless bean instance performs one operation on behalf of one client at a time. Once it has completed a method call, the instance can be pooled and reassigned to a different client, even during the same session.

A stateful bean instance performs a series of operations on behalf of one client at a time. Once that client's session is complete, the bean instance is destroyed, not pooled.

Application examples

A stateless bean could represent a catalog viewer. The bean's one method lets the end user look up an item in an online catalog.

A stateful bean could represent an online shopping cart that invokes several methods to accumulate items until the end user is ready to start processing the entire order.


Container-Managed or Bean-Managed Transactions

As is discussed in more detail in Chapter 2, you must specify whether your bean's container or the bean itself will manage the bean's transactions. TABLE 3-2 summarizes the differences between these choices.

TABLE 3-2 Deciding Between Container-Managed and Bean-Managed Transactions

Issue

Container-Managed Transactions

Bean-Managed Transactions

How transaction boundaries are set

The EJB container decides when to begin and commit a transaction according to the Java 2 Platform, Enterprise Edition Specification.

The programmer explicitly codes the transaction's boundaries to obtain finer-grained control over transactions.

Transaction manager

The container itself is the transaction manager.

To manage transactions, use JTA, which can include transactions for other resources such as JDBC.

Transactions and methods

One transaction is allowed per method. However, a method does not have to be associated with a transaction.

This case is more complex, but you can code more than one transaction per method.


In a typical enterprise bean using container-managed transactions (CMT), the container begins the transaction just before a method starts and commits the transaction just before the method exits. With CMT, you can let the client control the transaction. For example, a client might string together a logical business transaction by using different methods called by a stateful CMT session bean.

In a session bean with bean-managed transactions (BMT), you must specify in the code where a transaction begins and ends.


Defining a Session Bean

The EJB Builder wizard automates much of the task of creating the default classes that your session bean requires: a bean class, and the interfaces you choose (remote, local, or both remote and local). To define a session bean, you take the following steps:

1. Select or create a package to contain the session bean.

2. Use the EJB Builder wizard to generate the infrastructure of your session bean.

3. Add one or more business methods to the session bean.

4. Complete the bodies of the create and business methods.

These basic steps are explained in detail next.

Creating a Package

If you need to create a package to house your session bean, do as follows:

1. In the IDE's main window, if the Explorer is not already open, choose View right arrow Filesystems to open the Explorer window to the Filesystems tab.

2. In the Filesystems tab of the Explorer, select a filesystem, right-click, and choose New right arrow All Templates.

The New wizard opens the Choose Template page.

3. Select Java Package and click Next.

The wizard displays the New Object Name page.

4. Type a name for the package and click Finish.

The new Java package appears under your filesystem node.

Starting the EJB Builder Wizard

When you're ready to create a session bean, do as follows:

1. In the Filesystems tab of the Explorer, select the package where you want your session bean to reside.

2. Right-click and choose New right arrow All Templates.

The New wizard opens the Choose Template page.

3. Expand the J2EE node, choose Session EJB, and click Next.

The New wizard opens the Session EJB Builder to the Session Bean Name and Properties page. Notice that the panel on the left shows the current step and the steps you still must complete before your entity bean is created.

Generating the Default Session Bean

In the wizard's Session Bean Name and Properties page, you must make choices about state, transaction type, and type of interfaces. Do as follows:

1. Type a name for your session bean, and select the type of session bean you need.

Click the appropriate buttons to specify your bean's state, transaction mode, and which type of interfaces to implement. FIGURE 3-1 shows your choices. Notice the defaults: Stateless, Container-Managed, and Remote Interface Only.

 FIGURE 3-1 Possible Wizard Selections for a Session Bean

Screenshot showing the EJB Builder Wizard's first pane and selections for a session bean.

Note - The selections you make in this first page of the wizard determine the code that the wizard generates. If you later want to change any of these most basic selections, you can use the bean's property sheets as described in Chapter 8.



2. Click Next.

The Session Bean Class Files page appears as shown next. This example illustrates a stateless session bean.

Screenshot showing the EJB Builder Wizard's second pane, listing the classes about to be generated for a session bean.  

For a stateful session bean, you have an additional selection to make: Session Synchronization.

Screenshot showing part of the EJB Builder Wizard's second pane, with the Implement Session Synchronization Interface checkbox selected. 

This selection is explained in TABLE 3-4 and in Using Session Synchronization.

3. Check the bean class and interfaces, and change them if necessary.

The classes that make up your session bean are shown with their paths in this page.

If you specify any classes outside the named package, the resulting bean classes appear differently than shown in FIGURE 3-2.

Before you change these fields, also consider the following points:

4. Click Finish when you're done.

The wizard automatically generates the various parts of your session bean's infrastructure. These parts are discussed next.


Looking at a Session Bean's Classes

The EJB Builder wizard generates the default session bean classes for you and sets up the relationships between all the classes. FIGURE 3-2 shows how a typical session bean (all of whose classes are in the same package) appears in the Explorer's Filesystems tab.

 FIGURE 3-2 Default Classes of a Typical Session Bean With Remote Interfaces

Screenshot showing the typical classes generated for a session bean.[ D ]

The nodes marked with the class icon Class node icon. represent classes of the session bean. The node marked with the bean icon Bean icon. is a logical node for the session bean. Do all your editing in the logical node. The example bean's primary nodes are described next.

Expanding the Nodes

When you expand the four nodes under your session bean's package node, you see something like the tree view in FIGURE 3-3.

 FIGURE 3-3 Explorer's Detailed View of a Typical Session Bean With Remote Interfaces

Screenshot showing an expanded view of the typical classes generated for a session bean.[ D ]

Reviewing the Generated Classes

The EJB Builder has automatically placed the signatures for a create method and several life-cycle methods in your session bean class. These methods are discussed next.

Default Create Method

The wizard places the following ejbCreate method signature in every session bean class:

public void ejbCreate() { 
} 

The corresponding create method is placed in the session bean's home interface:

public interface AcctBalHome extends javax.ejb.EJBHome { 
	public session.AcctBal create() 
			throws javax.ejb.CreateException,
				java.rmi.RemoteException; 
} 

See Completing Create Methods for more information.

Life-Cycle Methods

The wizard adds to the bean class of any session bean signatures for the life-cycle methods shown next.

public void setSessionContext(javax.ejb.SessionContext aContext) { 
	context = aContext; 
} 
public void ejbActivate() {
} 
public void ejbPassivate() { 
} 
public void ejbRemove() { 
} 

TABLE 3-3 shows the purposes of these methods in the session bean class.

TABLE 3-3 Purpose of Life-Cycle Methods In a Session Bean Class

Method

Purpose

setSessionContext

This method lets you store the SessionContext reference in a field and populate instance variables. You can use it to allocate resources that last for the session bean's lifetime, resources such as a database-connection factory. By default, the EJB Builder wizard generates code that assigns the SessionContext to a field named context.

ejbActivate

This method initializes the bean, prepares it for use, and acquires the resources needed by the instance.

ejbPassivate

Before the bean instance is passivated, this method releases the resources the bean was using.

ejbRemove

This method releases resources that were acquired within the ejbCreate and business methods.


If you have opted to have your session bean use the session-synchronization interface, the wizard generates three more methods in the bean class:

public void afterBegin() { 
} 
public void afterCompletion(boolean committed) { 
} 
public void beforeCompletion() { 
} 

The session-synchronization methods are explained in TABLE 3-4.

TABLE 3-4 Purpose of Session-Synchronization Methods in a Session Bean Class

Method

Purpose and Use

afterBegin

This method tells the instance that a new transaction has begun. The EJB container calls the method right before it calls the business method. In afterBegin, you can load instance variables from the database.

beforeCompletion

This method tells the instance that a business method has completed, but the transaction has not been committed yet. This is the session bean's last chance to roll back the transaction. If the database hasn't yet been updated with the instance variables, you can code that update in the method body.

afterCompletion

This method tells the instance that the transaction has completed. In its one parameter, the Boolean value true means the transaction was committed, and false means the transaction was rolled back. If the transaction failed and was rolled back, this method can make the session bean refresh its instance variables from the database.



Completing Your Session Bean

The steps to completion of your session bean vary according to the type of bean you have chosen. Guidelines follow for:

Using Recommended Approaches When Working With Enterprise Beans

Appendix A discusses the best ways to make changes in your enterprise beans, and the errors and anomalies that you might see if you use other approaches. As a general rule, you should work through the logical node rather than the individual class nodes, use the bean's property sheets or the Customizer dialog box to edit methods, and use the IDE's Source Editor to complete or edit any bean code that isn't available to you through one of the dialog boxes.

Completing Create Methods

If your bean is stateless, it takes only one create method, which can have no parameters. A stateless session bean can contain no user-specific or client-specific data.

If your bean is stateful, it can have one or more create methods, each of which can have parameters.

In any case, work under the logical node. Open the create method in the Source Editor by selecting the node labeled create(), right-clicking, and choosing Open. Finish coding the body of the create method in the Source Editor.

Completing a Stateless Bean's Create Method

In a stateless session bean, the create method is often used to connect to resources. For example, this method can look up a resource-factory reference and store it as a field, so that JDBC connections can be acquired in later method calls.

Completing a Stateful Bean's Create Methods

In a stateful session bean, you can use a create method's parameters to look up a resource-factory reference or to send client-specific information (such as a user name and password), as shown in CODE EXAMPLE 3-1. The method can store the information for later use. Notice that this create method uses a helper class, IdVerifier.

CODE EXAMPLE 3-1 Create Method in a Stateful Session Bean
public void ejbCreate(String userid, String pwd) 
	throws CreateException {
 
	if (userid == null) {
			throw new CreateException("Please enter a user ID.");
	}
	else {
			this.userid = userid;
	}
 
	IdVerifier idChecker = new IdVerifier();
	if (idChecker.validate(pwd)) {
			this.pwd = pwd;
	}
	else {
			throw new CreateException("Invalid password: " + pwd);
	}
 
	contents = new Vector();
}

Adding a Create Method to a Stateful Bean

To add one or more create methods to your stateful session bean, do as follows:

1. Select the bean's logical node, right-click, and choose Add Create Method.

The Add Create Method dialog box appears.

2. Type a method name starting with create, add parameters and exceptions as necessary, and click OK.

The create method signature is generated in your bean's home interface and the corresponding ejbCreate method is generated in the bean class.

3. Finish any coding needed in the Source Editor.

Under the bean's logical node, expand the Classes node, select Bean Class, right-click, and choose Open.

Completing Life-Cycle Methods

The EJB Builder has generated four life-cycle methods for you. For a stateless session bean, the generated methods are sufficient. In a stateful session bean, you might need to add code to two of these methods: ejbPassivate and ejbActivate.

For example, your stateful bean might contain nonserializable fields that became serializable by replacing references. Or, your bean's conversational state might contain open resources, which the container can't retain when the bean's instance is passivated. In each case, you must complete the ejbPassivate method to release the nonserializable fields. Then complete the corresponding ejbActivate method to restore those fields.

Completing the ejbPassivate Method

This method must leave the instance fields ready to be serialized by the container. For example, as shown in CODE EXAMPLE 3-2, you must close all JDBC connections in this method and assign the instance's fields that store the connections to null.

CODE EXAMPLE 3-2 ejbPassivate Method
public void ejbPassivate() {
 
        try {
            con.close();
        } catch (Exception ex) {
            throw new EJBException("ejbPassivate Exception: " + 
						ex.getMessage());
			} finally { 
				con = null; 
        }  
    } 

Completing the ejbActivate Method

This method must make the instance fields available again, as demonstrated in CODE EXAMPLE 3-3.

CODE EXAMPLE 3-3 ejbActivate Method
public void ejbActivate() {
 
        try {
            InitialContext ic = new InitialContext();
            DataSource ds = (DataSource) ic.lookup(dbName);
            con =  ds.getConnection();
        } catch (Exception ex) {
            throw new EJBException("ejbActivate Exception: " + 
						ex.getMessage());
        }  
    }

Adding Business Methods

In a session bean, you add business methods to run business tasks for the client. Such a method in a session bean might access a database, or it might manage one or more entity beans that use their persistent fields to manipulate database entities.

To add a business method to your stateful session bean, do as follows:

1. Select the bean's logical node, right-click, and choose Add Business Method.

The Add Business Method dialog box appears.

2. Name the method, check to be sure the return type is appropriate, add parameters and exceptions as necessary, and click OK.

The business method signature is generated in your bean's remote interface and the corresponding method in the bean class.

3. Finish any coding needed in the Source Editor.

Under the bean's logical node, expand the Classes node, select Bean Class, right-click, and choose Open.

If your session bean needs access to the database, you might be able to reduce JDBC calls in the bean (and save system resources and network bandwidth) by encapsulating database access in a data access object (a DAO). A DAO can do the actual work of fetching data for the session bean. Using a DAO might make your session bean's code more simple and straightforward, and it might free your bean from dependence on a particular vendor tool or database.

Coding Transactions

The way you code transactions differs depending on whether your session bean is stateful or stateless, and whether it uses BMT or CMT. Guidelines follow for specifying transaction boundaries, dealing with rollbacks, and using the session-synchronization interface.

Understanding Transaction Spans

The allowable span of a transaction differs according to the type of session bean. TABLE 3-5 summarizes those differences. Notice that CMT and statefulness give a bean more flexibility.

TABLE 3-5 Relationship Between Transactions and Methods

In a stateless BMT bean (that manages its own transactions), a transaction can span only one method.

In a stateful BMT bean, a transaction can span one or more methods on the same session bean.

In a stateless CMT bean (whose transactions are managed by the container), a transaction can span more than one method, but each method must be on a different session bean.

In a stateful CMT bean, a transaction can span one or more methods on the same session bean.


Specifying Transaction Boundaries and Rollbacks

This section discusses guidelines for coding the starting and ending points of transactions in both CMT and BMT beans. Keep these two general rules in mind:

  • Nested transactions are not allowed in session beans or in JTA code.
  • Code is easier to maintain when JDBC and JTA transactions are not mixed. JTA is generally preferable because it can include transactions for other resources, including JDBC.
In CMT Beans

In a CMT bean, all transactions' boundaries are set by the EJB container, which means that you don't specify where a transaction begins or ends. Usually, the EJB container begins a transaction just before a method starts and commits the transaction just before the method ends.

Don't call any method that could interfere with the container's transaction boundaries. Problematic methods are:

  • commit, setAutoCommit, and rollback methods of java.sql.Connection
  • getUserTransaction method of javax.ejb.EJBContext
  • Any method of javax.transaction.UserTransaction

A session bean can roll back a container-managed transaction in two ways:

  • If a system exception is thrown, the container automatically rolls back the transaction.
  • Calling the setRollBackOnly method of javax.ejb.EJBContext tells the container to roll back the transaction even if an application exception is thrown.
In BMT Beans

In a BMT bean, you must explicitly code the beginning and ending of each transaction. Demarcate transaction boundaries explicitly, using the interface javax.transaction.UserTransaction. In the following code sample, the JTA interface is used:

UserTransaction ut = ejbContext.getUserTransaction();	ut.begin();	// perform transactional work here 	ut.commit();

When the updates specified by a transaction are saved, the transaction ends with a commit. When the transaction fails, it is rolled back, which means that the effects of all statements in the transaction are undone. When you provide for rollbacks in a session bean with BMT, don't use the methods getRollbackOnly or setRollbackOnly. Those two methods are for use only with an EJB container.

Using Session Synchronization

A stateful CMT session bean can use the session-synchronization interface, which gives the bean more control over database data cached within transactions.

This interface provides callback methods that the EJB container calls before starting, committing, or rolling back a transaction. Using this interface, a session bean's instance variables are automatically synchronized with their corresponding values in the database at specific stages in the transaction. If the transaction doesn't complete, the session bean can roll back the values of the bean's instance variables.

  • afterBegin. The container calls this method on the session bean before the first business method within a transaction. Youcan code this method to do any database work required by the instance within the scope of the transaction.
  • beforeCompletion. The container calls this method when the session bean's client has completed work on its current transaction but before committing the resource managers used by the instance. You can code this method to write out any database updates the bean has cached. In this method, you can also cause the transaction to roll back by invoking the setReadbackOnly method on its session context.
  • afterCompletion. The container calls this method to signal that the current transaction has completed. The status True is sent if the transaction committed, and False if the transaction was rolled back. You can code this method to manually reset the instance's state if the transaction was rolled back.

To add the session-synchronization interface to your session bean, make the following choices in the wizard:

1. In the first page of the session bean wizard, in the State section, choose Stateful.

2. In the second page of the wizard, choose Implement Session Synchronization Interface.

As a result, code like that shown in CODE EXAMPLE 3-4 is inserted into your session bean class. In the example, checkingBalance and savingBalance variables have been loaded into the afterBegin method.

CODE EXAMPLE 3-4 Example of an afterBegin Method
public void afterBegin() {
	System.out.println("afterBegin()");
	try {
			checkingBalance = selectChecking();
			savingBalance = selectSaving();
	} catch (SQLException ex) {
			throw new EJBException("afterBegin Exception: " +
				ex.getMessage());
	}
}

The sample afterCompletion method shown in CODE EXAMPLE 3-5 allows the account-balance fields in the session bean to be refreshed from the database if the transaction fails and is rolled back.

CODE EXAMPLE 3-5 Example of an afterCompletion Method
public void afterCompletion(boolean committed) {
	System.out.println("afterCompletion: " + committed);
	if (committed == false) {
			try {
				checkingBalance = selectChecking();
				savingBalance = selectSaving();
			} catch (SQLException ex) {
				throw new EJBException("afterCompletion SQLException: " +
						ex.getMessage());
			}
	}
}


After Creating Your Session Bean

Your session bean still needs to be prepared to work in its eventual environment. For information on the deployment descriptor, how to use property sheets, and other considerations of module assembly and application deployment, see Chapter 8.

Recommendations for working with finished enterprise beans are given in Appendix A.


Further Reading

Enterprise beans can be a very powerful and flexible part of your application. Creating the basic parts of an enterprise bean can be very simple, especially with a tool like the Sun ONE Studio 5 IDE. However, completing the bean so that it fulfills the needs of your application can be very complex. For details, refer to Enterprise JavaBeans Specification, version 2.0 at:
http://java.sun.com/products/ejb/docs.html