Previous Next Contents Index


Using Session EJBs to Manage Business Rules

This chapter describes how to create session Enterprise JavaBeans (EJBs) that encapsulate your application's business rules and business objects.

Specifically, this chapter explains how to use session beans to encapsulate repetitive, time-bound, and user-dependent tasks that represent the transient needs of a single, specific user.

This chapter includes the following sections:


Introducing Session EJBs
Much of a standard, distributed application consists of logical units of code that perform repetitive, time-bound, and user-dependent tasks. These tasks can be simple or complex, and they are often needed in different applications. For example, banking applications must verify a user's account ID and balances before performing a fund transfer of any kind. These kinds of tasks define the business rules and business logic that you use to run your business. Such discrete tasks, transient by nature, are perfect candidates for session Enterprise JavaBeans (EJBs).

Session EJBs are self-contained units of code that represent client-specific instances of generic objects. These objects are transient in nature, created and freed throughout the life of the application on an as-needed basis. For example, the "shopping cart" employed by many web-based, on-line shopping applications is a typical session bean. It is created by the on-line shopping application only when you start choosing items to buy. When you finish selecting items, the price of the items in your cart is calculated, your order is placed, and the shopping cart object is freed. You can continue to browse merchandise in the on-line catalogue, and if you decide the place another order, a new shopping cart is created for you.

Often, a session EJB has no dependencies on or connections to other application objects. For example, a shopping cart bean might have a data list member for storing item information, a data member for storing the total cost of items currently in the cart, and methods for adding, subtracting, reporting, and totaling items. On the other hand, the shopping cart might not have a live connection to the database of all items available for purchase. The application—or more accurately, the container for the session bean—maintains the database connection for all session beans in the application, and merely passes information from the database to the shopping cart bean as needed.

Session beans can either be "stateless" or "stateful." A stateless session bean is completely transient and encapsulates a temporary piece of business logic needed by a specific client for a limited time span. A stateful session bean is also transient, uses a "conversational state" to preserve information about its contents and values between client calls. The conversational state enables the container to maintain information about the state of the session bean and to recreate that state at a later point in program execution when needed.

The defining characteristics of a session bean have to do with its non-persistent, independent status within an application. One way to think of a session bean is as a temporary, logical extension of a client's application that runs instead on the application server. A session bean:

Generally, a session bean does not represent shared data in a database, but obtains a snapshot of data. The bean can, however, update data. Optionally, a session bean can also be transaction-aware. Its operations can take place in the context of a transaction managed by the bean.

A client accesses a session bean through the bean's remote interface, EJBObject. An EJB object is a remote Java programming language object accessible from the client through standard Java APIs for remote object calls. The EJB lives in the container from its creation to its destruction, and the container manages the EJB's life cycle and support services. Where an EJB resides or executes is transparent to the client that accesses it. Finally, multiple EJBs can be installed in a single container. The container provides services that allow clients to look up the interfaces of installed EJB classes through the Java Naming and Directory Interface (JNDI).

A client never accesses instances of a session bean directly. Instead, a client uses the session bean's remote interface to access a bean instance. The EJB object class that implements a session bean's remote interface is provided by the container. At a minimum, an EJB object supports all of the methods of the java.ejb.EJBObject interface. This includes methods to obtain the home interface for the session bean, to get the object's handle, to test if the object is identical to another object, and to remove the object. These methods are stipulated by the EJB Specification. (All specifications are accessible from installdir/nas/docs/index.htm, where installdir is the location in which you installed NAS.)

In addition, most EJB objects also support specific business logic methods. These are the methods at the heart of your applications.


Session Bean Components
When you code a session bean you must provide the following class files:

Creating the Remote Interface A session bean's remote interface defines a user's access to a bean's methods. All remote interfaces extend javax.ejb.EJBObject. For example:

import javax.ejb.*;
import java.rmi.*;
public interface MySessionBean extends EJBObject {
// define business method methods here....
}
The remote interface defines the session bean's business methods that a client calls. The business methods defined in the remote interface are implemented by the bean's container at run time. For each method you define in the remote interface, you must supply a corresponding method in the bean class itself. The corresponding method in the bean class must have:

Besides the business methods you define in the remote interface, the EJBObject interface defines several abstract methods that enable you to retrieve the home interface for the bean, to retrieve the bean's handle, which is its unique identifier, to compare the bean to another bean to see if it is identical, and to free, or remove the bean when it is no longer needed. When you implement beans, do not override these built-in methods.

For more information about these built-in methods and how they are to be used, see the EJB Specification. All specifications are accessible from installdir/nas/docs/index.htm, where installdir is the location in which you installed NAS.

Declaring vs. Implementing the Remote Interface

A bean class definition must include one matching method definition, including matching method names, arguments, and return types, for each method defined in the bean's remote interface. The EJB specification also permits the bean class to implement the remote interface directly, but recommends against this practice to avoid inadvertently passing a direct reference (via this) to a client in violation of the client-container-EJB protocol intended by the specification.

Creating the Class Definition For a session bean, the Bean class must be defined as public, and cannot be abstract. The Bean class must implement the javax.ejb.SessionBean interface. For example:

import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public class MySessionBean implements SessionBean {

// Session Bean implementation. These methods must always included.
public void ejbActivate() throws RemoteException { }
public void ejbPassivate() throws RemoteException { }
public void ejbRemove() throws RemoteException{ }
public void setSessionContext(SessionContext ctx) throws RemoteException { }
// other code omitted here.... }
The session bean must also implement one or more ejbCreate(...) methods. There should be one such method for each way a client is allowed to invoke the bean. For example:

public void ejbCreate() {
string[] userinfo = {"User Name", "Encrypted Password"} ;
}
Each ejbCreate(...) method must be declared as public, return void, and be named ejbCreate. Arguments, if any, must be legal types for Java RMI. The throws clause, may define application-specific exceptions, may include java.rmi.RemoteException or java.ejb.CreateException.

All useful session beans also implement one or more business methods. These methods are usually unique to each bean and represent its particular functionality. For example, if you define a session bean to manage user logins, it might include a unique function called ValidateLogin().

Business method names can be anything you want, but must not conflict with the names of methods used in the EJB architecture. Business methods must be declared as public. Method arguments and return value types must be legal for Java RMI. The throws clause may define application-specific exceptions, and must include java.rmi.RemoteException.

There are really two types of business methods you may implement in a session bean: internal ones, that are used by other business methods in the bean, but are never accessed outside the bean itself; and external ones, that are referenced by the session bean's remote interface.

Finally, there are a couple of optional interface implementations permitted in a session bean class definition, particularly javax.ejb.SessionSynchronization, which enables a session bean instance to be notified of transaction boundaries and synchronize its state with those transactions. For more information about this interface, see the EJB Specification. All specifications are accessible from installdir/nas/docs/index.htm, where installdir is the location in which you installed NAS.

Session Timeout
The container removes inactive session beans after they are inactive for a specified (or default) time. This timeout value is set in the bean's property file. For more information, see Specifying Session Timeout.

Passivation and Activation
You can "passivate" a bean rather than destroying it. Passivation returns the bean to a pool of active beans so that it can be later reactivated rather than reinstantiating a new bean.

You can control passivation in the ejbPassivate() and ejbActivate() methods. The container calls these methods to passivate or activate a bean.

The container passivates session beans after they are inactive for a specified (or default) time. This timeout value is set in the bean's property file. For more information, see Specifying Passivation Timeout.

For more information about passivation, see the EJB specification. All specifications are accessible from installdir/nas/docs/index.htm, where installdir is the location in which you installed NAS.

Creating the Home Interface The home interface defines the methods that enable a client using your application to create and remove session objects. A home interface always extends javax.ejb.EJBHome. For example:

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

public interface MySessionBeanHome extends EJBHome { MySessionBean create() throws CreateException, RemoteException; }
As this example illustrates, a session bean's home interface defines one or more create methods. Each such method must be named create, and must correspond in number and type of arguments to an ejbCreate method defined in the session bean class. The return type for each create method, however, does not match the return type of its corresponding ejbCreate method. Instead, it must return the session bean's remote interface type.

All exceptions defined in the throws clause of an ejbCreate method must be defined in the throws clause of the matching create method in the remote interface. In addition, the throws clause in the home interface must always include javax.ejb.CreateException.

All home interfaces automatically define two remove methods for destroying an EJB when it is no longer needed. Do not override these methods.


Additional Session Bean Guidelines
Before you decide what parts of your application you can represent as session beans, you should know a few more things about session beans. A couple of these things are related to the EJB specification for session beans, and a couple are specific to NAS and its support for session beans.

Creating Stateless or Stateful Beans The EJB specification describes two state management modes for session beans:

The NAS container supports both state management modes, so you may choose the state most appropriate for your session beans. Use stateless session beans as much as possible for performance reasons. In general, stateless session beans also scale more efficiently in a highly distributed environment. All session beans must be serializable, Because stateful session beans contain much state information that must be both serializable and capable of being recreated, they tend to perform less efficiently and scale less well in a highly distributed environment.

If you decide to use stateful session beans, plan to co-locate stateful beans with their clients. Also, use sticky load balancing to reduce the number of remote procedure calls, especially for session beans that are passivated and activated frequently or for session beans that use many resources, such as database connections and handles.

Accessing NAS Functionality You can develop session beans that adhere strictly to the EJB Specification, you can develop session beans that take advantage both of the specification and additional, value-added NAS features, and you can develop session beans that adhere to the specification in non-NAS environments, but that take advantage of NAS features if they are available. Make the choice that is best for your intended deployment scenario.

NAS offers several features through the NAS container and NAS APIs that enable your applications to take programmatic advantage of specific features of the NAS environment. You can embed API calls in your session beans if you plan on using those beans only in the NAS environment.

For example, you can trigger a named application event from an EJB using the IAppEventMgr interface, using the following steps and example:

  1. First obtain an instance of com.kivasoft.IContext by casting javax.ejb.SessionContext or javax.ejb.EntityContext to IServerContext.
  2. Next, use the GetAppEventMgr() method in the GXContext class to create an IAppEventMgr object.
  3. Finally, trigger the application event with triggerEvent().
  4. javax.ejb.SessionContext m_ctx; 
    .... 
    com.netscape.server.IServerContext sc; 
    sc = (com.netscape.server.IServerContext) m_ctx; 
    com.kivasoft.IContext kivaContext = sc.getContext();
    IAppEventMgr mgr = com.kivasoft.dlm.GXContext.GetAppEventMgr(ic);
    mgr.triggerEvent("eventName");
    
Serializing Handles and References The EJB Specification indicates that to guarantee serializable bean references, you should use handles rather than direct references to EJBs.

NAS direct references are also serializable. You may wish to take advantage of this extension, but you should be aware that not all vendors support it.

Managing Transactions Many session beans interact with databases. You can control transactions in beans using settings in the bean's property file. This permits you to specify transaction management at bean design time, deployment time, and run time. By having a bean handle transaction management you are freed from having explicitly to start, roll back, or commit transactions in the bean's database access methods.

By moving transaction management to the bean level, you gain the ability to place all of a bean's activities—even those not directly tied to database access—under the same transaction control as your database calls. This guarantees that all parts of your application controlled by a session bean run as part of the same transaction, and either everything the bean undertakes is committed, or is rolled back in the case of failure. In effect, bean-managed transactional state permits you to synchronize your application without having to code any synchronization routines.

Committing a Transaction When a session bean signals that it is time to commit a transaction, the actual commit process is handled by the bean's container. Besides affecting the data your application processes, commit time also affects the state of a session bean. The NAS container implements commit option C as described in the EJB specification.

When a commit occurs, it signals to the container that the session bean has completed its useful work, and should synchronize its state with the underlying data store. The container permits the transaction to complete, and then frees the bean. Result sets associated with a committed transaction are no longer valid. Subsequent requests for the same bean cause the container to issue a load to synchronize state with the underlying data store.

Note that transactions begun in the container are implicitly committed. Also, any participant can roll back a transaction. For more information about transactions, see Handling Transactions with EJBs.

Accessing Databases Many session beans access and even update data. Because of the transient nature of session beans, however, be careful about how that access takes place. In general, use the JDBC API to make your calls, and always use the transaction and security management methods described in Handling Transactions with EJBs to manage transaction isolation level and transaction requirements at the bean level.

For more information see Using JDBC for Database Access.


Determining the Business Rules in Your Applications
When you adopt the NAS application programming model defined in this book, you split your application into general parts. For example, you separated your presentation logic from your business logic and business entities, such as databases. You also determined which part(s) of your application were best handled as servlets, the central dispatcher for your application. What's left is the heart of your application, its business—logical flow, access rights, calculating, processing, and data access. The next step is to separate what are business entities from what are business rules and business logic.

Choosing a Coarse Bean Granularity In many cases business rules may well involve database access. For example, if you are building an enterprise-wide employee database access program, there may be discrete business rules about what employees can access which parts of the database. For example, you will want to grant access to names, telephone extension, and email address information to all of your employees so they can contact one another. On the other hand, perhaps only managers and payroll employees will have access to employee compensation information, and perhaps only certain payroll employees will actually be able to update the employee compensation information. In these cases, there are different database access rules for each category of employee. Is each of these categories a candidate for a separate session bean, or should you write a larger, more sophisticated session bean that can handle all different employee types?

In general, you should create your application out of as few beans as reasonable. An application with fewer, larger beans significantly outperforms an application with many, smaller beans because there is less system overhead, and fewer remote procedure calls to process. Otherwise, there is no hard and fast rule about where the boundary lies.

One option might be to create a session bean that determines employee access rights and then passes that information as an argument to a single database access session bean. The questions here are as follows:

The smaller the elements you break your application into, the easier it becomes to isolate functionality and maintain it. In addition, many smaller elements tend to be more generic, and easier to reuse in other applications. On the other hand, the more elements you use to construct a composite enterprise application, the more system overhead there is, and the slower your application may run. In general, unless your site has many applications it uses, it is always best to balance the ease of maintenance and reuse with the speed and performance of your applications.

Performance Considerations

As a bean developer, you can make choices that affect the application's speed and performance at bean design time. For example, to increase performance, you may choose to create fewer, larger beans that are not as easily reusable in other applications. You may choose to group database access and updates to minimize data traffic.

There is no hard and fast rule for affecting application speed, except that fewer, larger, stateless beans tend to produce a faster application than many smaller or stateful beans. You should work with your system administrator to anticipate how your application will be deployed and how many users will access the system at the same time. Armed with that information, you can make wiser choices about how to divide your business rules across session EJBs.

 

© Copyright 1999 Netscape Communications Corp.