home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Book Home Enterprise JavaBeans Search this book

Chapter 2. Architectural Overview

As you learned in Chapter 2, "Architectural Overview", Enterprise JavaBeans is a component model for component transaction monitors, the most advanced type of business application server available today. To effectively use Enterprise JavaBeans, you need to understand the EJB architecture, so this book includes two chapters on the subject. This chapter explores the core of EJB: how enterprise beans are distributed as business objects. Chapter 3, "Resource Management and the Primary Services" explores the services and resource management techniques supported by EJB.

To be truly versatile, the EJB component design had to be smart. For application developers, assembling enterprise beans is simple, requiring little or no expertise in the complex system-level issues that often plague three-tier development efforts. While EJB makes it easy for application developers, it also provides system developers (the people who write EJB servers) with a great deal of flexibility in how they support the EJB specification.

The similarities among different component transaction monitors (CTMs) allow the EJB abstraction to be a standard component model for all of them. Each vendor's CTM is implemented differently, but they all support the same primary services and similar resource management techniques. The primary services and resource management techniques are covered in more detail in Chapter 3, "Resource Management and the Primary Services", but some of the infrastructure for supporting them is addressed in this chapter.

2.1. The Enterprise Bean Component

Enterprise JavaBeans server-side components come in two fundamentally different types: entity beans and session beans. A good rule of thumb is that entity beans model business concepts that can be expressed as nouns. For example, an entity bean might represent a customer, a piece of equipment, an item in inventory, or even a place. In other words, entity beans model real-world objects; these objects are usually persistent records in some kind of database. Our hypothetical cruise line will need entity beans that represent cabins, customers, ships, etc.

Session beans are an extension of the client application and are responsible for managing processes or tasks. A Ship bean provides methods for doing things directly to a ship but doesn't say anything about the context under which those actions are taken. Booking passengers on the ship requires that we use a Ship bean, but also requires a lot of things that have nothing to do with the Ship itself: we'll need to know about passengers, ticket rates, schedules, and so on. A session bean is responsible for this kind of coordination. Session beans tend to manage particular kinds of activities, for example, the act of making a reservation. They have a lot to do with the relationships between different enterprise beans. A TravelAgent session bean, for example, might make use of a Cruise, a Cabin, and a Customer--all entity beans--to make a reservation.

The activity that a session bean represents is fundamentally transient: you start making a reservation, you do a bunch of work, and then it's finished. A session bean doesn't represent something in a database. Obviously, session beans have lots of side effects on the database: in the process of making a reservation, you might create a new Reservation by assigning a Customer to a particular Cabin on a particular Ship. All of these changes would be reflected in the database by actions on the respective entity beans. Session beans like TravelAgent, which is responsible for making a reservation on a cruise, can even access a database directly and perform reads, updates, and deletes to data. But there's no TravelAgent record in the database--once the reservation is made, it's done.

What makes this distinction difficult is that it's extremely flexible. The relevant distinction for Enterprise JavaBeans is that an entity bean has persistent state; a session bean models interactions but doesn't have persistent state.

2.1.1. Classes and Interfaces

A good way to understand the design of enterprise beans is to look at how you'd go about implementing one. To implement an enterprise bean, you need to define two interfaces and one or two classes:

Remote interface

The remote interface for an enterprise bean defines the bean's business methods: the methods a bean presents to the outside world to do its work. The remote interface extends javax.ejb.EJBObject, which in turn extends java.rmi.Remote. (We'll call the rather shadowy entity that actually implements this interface the EJB object.)

Home interface

The home interface defines the bean's life cycle methods: methods for creating new beans, removing beans, and finding beans. The home interface extends javax.ejb.EJBHome, which in turn extends java.rmi.Remote. (We'll call the object that implements the home interface the EJB home.)

Bean class

The bean class actually implements the bean's business methods. Note, however, that the bean class usually does not implement the bean's home or remote interfaces. However, it must have methods matching the signatures of the methods defined in the remote interface and must have methods corresponding to some of the methods in the home interface. If this sounds perfectly confusing, it is. We'll try to clarify this as we go along. An entity bean must implement javax.ejb.EntityBean; a session bean must implement javax.ejb.SessionBean. Both EntityBean and SessionBean extend javax.ejb.EnterpriseBean.

Primary key

The primary key is a very simple class that provides a pointer into the database. Only entity beans need a primary key; the only requirement for this class is that it implements java.io.Serializable.

The complexity--particularly all the confusion about classes implementing the methods of an interface but not implementing the interface itself--comes about because enterprise beans exist in the middle between some kind of client software and some kind of database. The client never interacts with a bean class directly; it always uses the methods of the bean's home and remote interfaces to do its work, interacting with stubs that are generated automatically. (For that matter, a bean that needs the services of another bean is just another client: it uses the same stubs, rather than interacting with the bean class directly.)

There are also lots of interactions between a bean and its server. These interactions are managed by a "container," which is responsible for presenting a uniform interface between the bean and the server. (Although it's incorrect, many people use the terms "container" and "server" interchangeably. We won't promise consistency ourselves. But it's helpful to understand the difference.) The container is responsible for creating new instances of beans, making sure that they are stored properly by the server, and so on. Tools provided by the container's vendor do a tremendous amount of work behind the scenes. At least one tool will take care of creating the mapping between entity beans and records in your database. Other tools generate a lot of code based on the home interface, the remote interface, and the bean class itself. The code generated does things like create the bean, store it in the database, and so on. This code (in addition to the stubs) is what actually implements the two interfaces, and is the reason your bean class doesn't have to.

Before going on let's first establish some conventions. When we speak about an enterprise bean as a whole, its remote interface, home interface, bean class, and so forth, we will call it by its remote-interface name, followed by the word "bean." For example, an enterprise bean that is developed to model a cabin on a ship will be called the "Cabin bean." Notice that we didn't use a constant width font for "Cabin." We do this because we are referring to all the parts of the bean (remote interface, home interface, bean class, etc.) as a whole, not just one particular part like the remote interface or bean class. When we are talking about the remote interface of the Cabin bean we will use constant width. For example, the remote interface for the Cabin bean is called the Cabin remote interface. Likewise, we use constant width for the names of the classes that make up the other parts of the bean. The bean class itself would be called CabinBean, the home interface CabinHome, and the primary key would be called CabinPK.

2.1.1.1. The remote interface

Having introduced the machinery, let's look at how to build a bean. In this section, we will examine the Cabin bean, an entity bean that models a cabin on a cruise ship. Let's start with its remote interface.

We'll define the remote interface for a Cabin bean using the interface called Cabin, which defines business methods for working with cabins. All remote-interface types extend the javax.ejb.EJBObject interface.

import java.rmi.RemoteException;

public interface Cabin extends javax.ejb.EJBObject {
    public String getName() throws RemoteException;
    public void setName(String str) throws RemoteException;
    public int getDeckLevel() throws RemoteException;
    public void setDeckLevel(int level) throws RemoteException;
}

These are methods for naming the cabin and methods for setting the cabin's deck level; you can probably imagine lots of other methods that you'd need, but this is enough to get started. All of these methods declare that they throw RemoteException, which is required of any method that can be invoked through RMI. EJB requires the use of Java RMI-IIOP conventions, although the underlying protocol can be CORBA IIOP, Java Remote Method Protocol ( JRMP), or some other protocol. Java RMI-IIOP will be discussed in more detail in the next chapter.

2.1.1.2. The home interface

The home interface defines life-cycle methods and methods for looking up beans. The home interface extends javax.ejb.EJBHome. We'll call the home interface for the Cabin bean CabinHome and define it like this:

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.FinderException;

public interface CabinHome extends javax.ejb.EJBHome {
    public Cabin create(int id) 
        throws CreateException, RemoteException;
    public Cabin findByPrimaryKey(CabinPK pk)
        throws FinderException, RemoteException;
}

The create() method will be responsible for initializing an instance of our bean. If your application needs it, you can provide other create() methods, with different arguments.

In addition to the findByPrimaryKey(), you are free to define other methods that provide convenient ways to look up Cabin beans--for example, you might want to define a method called findByShip() that returns all the cabins on a particular ship. Find methods like these are only used in EntityBean types and are not used in SessionBean types.

2.1.1.3. The bean class

Now let's look at an actual bean. Here's the code for the CabinBean; it's a sparse implementation, but it will show you how the pieces fit together:

import javax.ejb.EntityContext;

public class CabinBean implements javax.ejb.EntityBean {

    public int id;
    public String name;
    public int deckLevel;
 
    // EJB 1.0: return void   
    public CabinPK ejbCreate(int id){
        this.id = id;
        // EJB 1.0 no return statement
        return null;
    }
    public void ejbPostCreate(int id){
        // do nothing
    }
    public String getName(){
        return name;
    }
    public void setName(String str){
        name = str;
    }
    public int getDeckLevel(){
        return deckLevel;
    }
    public void setDeckLevel(int level){
        deckLevel = level;
    }

    public void setEntityContext(EntityContext ctx){
        // not implemented
    }
    public void unsetEntityContext(){
        // not implemented
    }
    public void ejbActivate(){
        // not implemented
    }
    public void ejbPassivate(){
        // not implemented
    }
    public void ejbLoad(){
        // not implemented
    }
    public void ejbStore(){
        // not implemented
    }
    public void ejbRemove(){
        // not implemented
    }
}

NOTE

The //EJB1.0comments indicate how to modify the code to work with an EJB 1.0 server. As written, this code (and the other examples in this book) assume EJB 1.1, unless otherwise noted.

The set and get methods for the cabin's name and deck level are the business methods of the CabinBean; they match the business methods defined by the bean's remote interface, Cabin. The CabinBean class has state and business behavior that models the concept of a cabin. The business methods are the only methods that are visible to the client application; the other methods are visible only to the EJB container. The other methods are required by the EJB component model and are not really part of the bean class's public business definition.

The ejbCreate() and ejbPostCreate() methods initialize the instance of the bean class when a new cabin record is to be added to the database. The last seven methods in the CabinBean are defined in the javax.ejb.EntityBean interface. These methods are state management callback methods. The EJB server invokes these callback methods on the bean class when important state management events occur. The ejbRemove() method, for example, notifies an entity bean that its data is about to be deleted from the database. The ejbLoad() and ejbStore() methods notify the bean instance that its state is being read or written to the database. The ejbActivate() and ejbPassivate() methods notify the bean instance that it is about to be activated or deactivated, a process that conserves memory and other resources. setEntityContext() provides the bean with an interface to the EJB server that allows the bean class to get information about itself and its surroundings. unsetEntityContext() is called by the EJB server to notify the bean instance that it is about to be dereferenced for garbage collection.

All these callback methods provide the bean class with notifications of when an action is about to be taken, or was just taken, on the bean class's behalf by the EJB server. These notifications simply inform the bean of an event, the bean doesn't have to do anything about it. The callback notifications tell the bean where it is during its life cycle, when it is about to be loaded, removed, deactivated, and so on. Most of the callback methods pertain to persistence, which can be done automatically for the bean class by the EJB server. Because the callback methods are defined in the javax.ejb.EntityBean interface, the bean class must implement them, but it isn't required to do anything meaningful with the methods if it doesn't need to. Our bean, the CabinBean, won't need to do anything when these callback methods are invoked, so these methods are empty implementations. Details about these callback methods, when they are called and how a bean should react, are covered in Chapter 6, "Entity Beans".

2.1.1.4. The primary key

Certain public fields of an entity bean are stored in a database. These fields are called persistent fields. Determining how the data in the database relates to the persistent fields of the bean class is called data mapping. When a bean is deployed into an EJB server, its persistent fields must be mapped to the database. The data used to populate persistent fields in the bean instance is obtained using a primary key. The primary key is a pointer that helps locate data that describes a unique record or entity in the database; it is used in the findByPrimaryKey() method of the home interface to locate a specific entity. Primary keys are defined by the bean developer and must be some type of serializable object. Here's the primary key for the Cabin bean:

public class CabinPK implements java.io.Serializable{
    public int id;
    
    public int hashCode(){ 
         return id;
    }
    public boolean equals(Object obj){
        if (obj instanceof CabinPK){
            if (((CabinPK)obj).id == id)
                return true;
        }
        return false;
    }
}

Most EJB container vendors provide some kind of tool, available at deployment time, that helps to map the primary key and the bean's persistent fields to the database. These kinds of tools may present the persistent fields of the bean as well as the structure of the database in a graphical presentation. The person deploying the bean simply ties the bean's fields to its representation in the database, which could be relational database columns, an objectified version of the database, or a more direct mapping to an object database.

2.1.1.5. What about session beans?

CabinBean is an entity bean, but a session bean wouldn't be all that different. It would extend SessionBean instead of EntityBean; it would have an ejbCreate() method that would initialize the bean's state, but no ejbPostCreate(). Session beans don't have an ejbLoad() or ejbStore() because session beans are not persistent. While session beans have a setSessionContext() method, they don't have an unsetSessionContext() method. Finally, a session bean would provide an ejbRemove() method, which would be called to notify the bean that the client no longer needs it. However, this method wouldn't tell the bean that its data was about to be removed from the database, because a session bean doesn't represent data in the database.

Session beans don't have a primary key. That's because session beans are not persistent themselves, so there is no need for key that maps to the database.

2.1.2. Deployment Descriptors and JAR Files

Much of the information about how beans are managed at runtime is not addressed in the interfaces and classes discussed previously. You may have noticed, for example, that we didn't talk about how beans interact with security, transactions, naming, and other services common to distributed object systems. As you know from prior discussions, these types of primary services are handled automatically by the EJB CTM server, but the EJB server still needs to know how to apply the primary services to each bean class at runtime. To do this, we use deployment descriptors.

Deployment descriptors serve a function very similar to property files. They allow us to customize behavior of software (enterprise beans) at runtime without having to change the software itself. Property files are often used with applications, but deployment descriptors are specific to a class of enterprise bean. Deployment descriptors are also similar in purpose to property sheets used in Visual Basic and PowerBuilder. Where property sheets allow us to describe the runtime attributes of visual widgets (background color, font size, etc.), deployment descriptors allow us to describe runtime attributes of server-side components (security, transactional context, etc.). Deployment descriptors allow certain runtime behaviors of beans to be customized, without altering the bean class or its interfaces.

When a bean class and its interfaces have been defined, a deployment descriptor for the bean is created and populated with data about the bean. Frequently, IDEs (integrated development environments) that support development of Enterprise JavaBeans will allow developers to graphically set up the deployment descriptors using visual utilities like property sheets. After the developer has set all the properties for a bean, the deployment descriptor is saved to a file. Once the deployment descriptor is complete and saved to a file, the bean can be packaged in a JAR file for deployment.

JAR ( J ava ar chive) files are ZIP files that are used specifically for packaging Java classes (and other resources such as images) that are ready to be used in some type of application. JARs are used for packaging applets, Java applications, JavaBeans, and Enterprise JavaBeans. A JAR file containing one or more enterprise beans includes the bean classes, remote interfaces, home interfaces, and primary keys (EntityBean types only), for each bean. It also contains one deployment descriptor, which is used for all the beans in the JAR files. When a bean is deployed, the JAR's path is given to the container's deployment tools, which read the JAR file. The container uses the deployment descriptor to learn about the beans contained in the JAR file.

NOTE

EJB 1.0 also requires information in the JAR manifest (a kind of table of contents for the JAR), to denote which entry points to the deployment descriptor. When a bean is deployed, the JAR's path is given to the container's deployment tools, which read the JAR file. The first thing read out of the JAR file after the manifest is the deployment descriptor.

EJB 1.1 doesn't use the JAR's manifest; the first thing read in the JAR is the deployment descriptor.

When the JAR file is read at deployment time, the container tools read the deployment descriptor to learn about the bean and how it should be managed at runtime. The deployment descriptor tells the deployment tools what kind of beans are in the JAR file (SessionBean or EntityBean), how they should be managed in transactions, who has access to the beans at runtime, and other runtime attributes of the beans. The person who is deploying the bean can alter some of these settings, like transactional and security access attributes, to customize the bean for a particular application. Many container tools provide property sheets for graphically reading and altering the deployment descriptor when the bean is deployed. These graphical property sheets are similar to those used by bean developers.

The deployment descriptors help the deployment tools to add beans to the EJB container. Once the bean is deployed, the properties described in the deployment descriptors will continue to be used to tell the EJB container how to manage the bean at runtime.

2.1.2.1. EJB 1.0: Deployment descriptors

Enterprise JavaBeans Version 1.0 uses a set of serializable classes to set and store the deployment descriptor information. Instances of these classes are created and populated with deployment information when the bean is developed, then serialized to a file. The container deploying the bean deserializes the deployment descriptor objects and reads their properties to obtain the deployment information.

Here are some of the property methods defined in the main descriptor class, DeploymentDescriptor. The method bodies have been omitted; what's important at this stage is to get a feel for what methods are defined by a descriptor.

public abstract Class javax.ejb.deployment.DeploymentDescriptor 
    extends Object implements Serializable {

  // The release version of the bean
  protected int versionNumber;    
  
  // Get the AccessControlEntry objects for the enterprise bean.   
  public AccessControlEntry[] getAccessControlEntries() {}
  // Get the control descriptor at the specified index. 
  public ControlDescriptor getControlDescriptors(int index) {}
  // Get the enterprise bean's full class name. 
  public String getEnterpriseBeanClassName(){}
  // Get enterprise bean's environment properties. 
  public Properties getEnvironmentProperties() {} 
  // Get the full name of the enterprise bean's home interface. 
  public String getHomeInterfaceClassName() {} 
  // Get the full name of the enterprise bean's remote interface. 
  public String getRemoteInterfaceClassName() {} 

  // Set the AccessControlEntry objects for the enterprise bean.
  public void setAccessControlEntries(AccessControlEntry values []){}  
  // Set the control descriptor at the specified index. 
  public void setControlDescriptors(int index, ControlDescriptor value) {}
  // Set the enterprise bean's full class name. 
  public void setEnterpriseBeanClassName(String value) {}
  // Set enterprise bean's environment properties. 
  public void setEnvironmentProperties(Properties value) {}  
  // Set the full name of the enterprise bean's home interface. 
  public void setHomeInterfaceClassName(String value) {}
  // Specify that the enterprise bean is reentrant. 
  public void setReentrant(boolean value) {}
  // Set the full name of the enterprise bean's remote interface. 
  public void setRemoteInterfaceClassName(String value) {}  
  
  // ... Other set and get methods for properties follow.
}

The classes used to provide deployment information are found in the javax.ejb.deployment package, which has five deployment descriptor classes:

DeploymentDescriptor

The DeploymentDescriptor class is the abstract superclass for both EntityDescriptor and SessionDescriptor. It provides the accessor methods for reading properties that describe the bean's version number, and the names of the classes for the bean's remote interface, home interface, and bean class. In addition, the deployment descriptor provides access to the ControlDescriptors and AccessControlEntrys.

ControlDescriptor

The ControlDescriptor class provides accessor methods for defining the security and transactional attributes of a bean at runtime. ControlDescriptors can be applied to the bean as a whole, or to specific methods of the bean. Any method that doesn't have a ControlDescriptor uses the default properties defined by the ControlDescriptor for the bean itself. Security properties in the ControlDescriptor indicate how AccessControlEntrys are applied at runtime. Transactional properties indicate how the bean or specific method will be involved in transactions at runtime.

AccessControlEntry

Each AccessControlEntry identifies a person, group, or role that can access the bean or one of its methods. Like ControlDescriptor, AccessControlEntry can be applied to the bean as a whole or to a specific method. An AccessControlEntry that is specific to a method overrides the default AccessControlEntrys set for the bean. The AccessControlEntrys are used in combination with the security properties in the ControlDescriptor to provide more control over runtime access to the bean and its methods.

EntityDescriptor

The EntityDescriptor class extends DeploymentDescriptor to provide properties specific to an EntityBean object. Entity bean properties include the name of the primary key class and what instance variables are managed automatically by the container.

SessionDescriptor

The SessionDescriptor class extends DeploymentDescriptor to provide properties specific to a SessionBean object. Session bean properties include a timeout setting (how long a session can go unused before it's automatically removed) and a stateless session property. The stateless session property indicates whether the session is a stateless session bean or a stateful session bean. (More about stateless and stateful session beans later.)

Several of the properties described by the deployment descriptors, such as transactional and security attributes, have not yet been discussed. Later we will discuss these topics in more detail, but for now it's important that you understand that the deployment descriptors in EJB 1.0 are serialized class instances that describe the bean and some of its runtime behavior to the container.

2.1.2.2. EJB 1.1: Deployment descriptors

Enterprise JavaBeans 1.1 dropped the serializable deployment descriptor classes used in EJB 1.0 in favor of a more flexible file format based on XML (Ex tensible M arkup Language). The new XML deployment descriptors are text files structured according to a standard EJB DTD (Document Type Definition) that can be extended so the type of deployment information stored can evolve as the specification evolves. Chapter 10, "XML Deployment Descriptors" provides a a detailed description of EJB 1.1 deployment descriptors. This section provides a brief overview of XML deployment descriptors.

The following deployment descriptor might be used to describe the Cabin bean:

<?xml version="1.0"?>

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

<ejb-jar>
    <enterprise-beans>
        <entity>
            <ejb-name>CabinEJB</ejb-name>
            <home>com.titan.cabin.CabinHome</home>
            <remote>com.titan.cabin.Cabin</remote>
            <ejb-class>com.titan.cabin.CabinBean</ejb-class>
            <prim-key-class>com.titan.cabin.CabinPK</prim-key-class>
            <persistence-type>Container</persistence-type>
            <reentrant>False</reentrant>
        </entity>
    </enterprise-beans>
</ejb-jar>

The deployment descriptor for a real bean would have a lot more information; this example simply illustrates the type of information that you'll find in an XML deployment descriptor.

The second element in any XML document is !DOCTYPE. This element describes the organization that defined the DTD for the XML document, the DTD's version, and a URL location of the DTD. The DTD describes how a particular XML document is structured.

All the other elements in the XML document are specific to EJB 1.1. They do not represent all the elements used in deployment descriptors, but they illustrate the types of elements that are used. Here's what the elements mean:

ejb-jar

The root of the XML deployment descriptor. All other elements must be nested below this one. It must contain one enterprise-beans element as well as other optional elements.

enterprise-beans

Contains declarations for all the beans described by this XML document. It may contain entity and session elements, which describe entity beans and session beans respectively.

entity

Describes an entity bean and its deployment information. There must be one of these elements for every entity bean described by the XML deployment descriptor. (The session element is used in the same way to describe a session bean.)

ejb-name

The descriptive name of the bean. It's the name we use for the bean in conversation, when talking about the bean component as a whole.

home

The fully qualified class name of the home interface. This is the interface that defines the life-cycle behaviors (create, find, remove) of the bean.

remote

The fully qualified class name of the remote interface. This is the interface that defines the bean's business methods.

ejb-class

The fully qualified class name of the bean class. This is the class that implements the business methods of the bean.

prim-key-class

The fully qualified class name of the bean's primary key. The primary key is used to find the bean data in the database.

The last two elements in the deployment descriptor, the persistence-type and reentrant elements, express the persistence strategy and concurrency policies of the entity bean. These elements are explained in more detail later in the book.

As you progress through this book, you will be introduced to the elements that describe concepts we have not covered yet, so don't worry about knowing all of the things you might find in a deployment descriptor.

2.1.3. The Unseen Pieces

We've done a lot of hand waving about the strange relationships between an enterprise bean and its interfaces. Now it's time to talk a little more precisely about what's going on. Unfortunately, we can't talk as precisely as we'd like. There are a number of ways for an EJB container to implement these relationships; we'll show some of the possibilities.

The two missing pieces are the EJB object itself and the EJB home. You will probably never see the EJB home and EJB object classes because their class definitions are proprietary to the vendor's EJB implementation and are generally not made public. This is good because it represents a separation of responsibilities along areas of expertise. As an application developer, you are intimately familiar with how your business environment works and needs to be modeled, so you will focus on creating the applications and beans that describe your business. System-level developers, the people who write EJB servers, don't understand your business, but they do understand how to develop CTMs and support distributed objects. It makes sense for system-level developers to apply their skills to mechanics of managing distributed objects but leave the business logic to you, the application developer. Let's talk briefly about the EJB object and the EJB home so you understand the missing pieces in the big picture.

2.1.3.1. The EJB object

This chapter has said a lot about a bean's remote interface, which extends the EJBObject interface. Who implements that interface? Clearly, the client stub: we understand that much. But what about the server side?

On the server side, an EJB object is a distributed object that implements the remote interface of the bean. It wraps the bean instance--that is, the enterprise bean class you've created (in our example, the CabinBean)--on the server and expands its functionality to include javax.ejb.EJBObject behavior. The EJB object is generated by the utilities provided by the vendor of your EJB container and is based on the bean classes and the information provided by the deployment descriptor. The EJB object wraps the bean instance and works with the container to apply transactions, security, and other system-level operations to the bean at runtime. Chapter 3, "Resource Management and the Primary Services" talks more about the EJB object's role with regard to system-level operations.

There are a number of strategies that a vendor can use to implement the EJB object; Chapter 2, "Architectural Overview" illustrates three possibilities.

figure

Figure 2-1. Three ways to implement the EJB object

In Figure 2-1(a) you see that the EJB object is a classic wrapper because it holds a reference to the bean class and delegates the requests to the bean. Chapter 2, "Architectural Overview"(b) shows that the EJB object class actually extends the bean class, adding functionality specific to the EJB container. In Chapter 2, "Architectural Overview"(c), you see that the bean class is no longer included in the model. In this case, the EJB object has both a proprietary implementation required by the EJB container and bean class method implementations that were copied from the bean class's definition.

The EJB object design that is shown in Chapter 2, "Architectural Overview"(a) is perhaps the most common. Throughout this book, particularly in the next chapter, we will explain how EJB works with the assumption that the EJB object wraps the bean class instance as depicted in Figure 2-1(a). But the other implementations are used; it shouldn't make a difference which one your vendor has chosen. The bottom line is that you never really know much about the EJB object: its implementation is up to the vendor. Knowing that it exists and knowing that its existence answers a lot of questions about how enterprise beans are structured, should be sufficient. Everything that any client (including other enterprise beans) really needs to know about any bean is described by the remote and home interfaces.

2.1.3.2. The EJB home

The EJB home is a lot like the EJB object. It's another class that's generated automatically when you install an enterprise bean in a container. It implements all the methods defined by the home interface and is responsible for helping the container in managing the bean's life cycle. Working closely with the EJB container, the EJB home is responsible for locating, creating, and removing enterprise beans. This may involve working with the EJB server's resource managers, instance pooling, and persistence mechanisms, the details of which are hidden from the developer.

For example, when a create method is invoked on the home interface, the EJB home creates an instance of the EJB object which references a bean instance of the appropriate type. Once the bean instance is associated with the EJB object, the instance's matching ejbCreate() method is called. In the case of an entity bean, a new record is inserted into the database. With session beans the instance is simply initialized. Once the ejbCreate() method has completed, the EJB home returns a remote reference (i.e., a stub) for the EJB object to the client. The client can then begin to work with the EJB object by invoking business methods using the stub. The stub relays the methods to the EJB object; in turn, the EJB object delegates those method calls to the bean instance.

Figure 2-2 illustrates the architecture of EJB with the EJB home and EJB object implementing the home interface and remote interface respectively. The bean class is also shown as being wrapped by the EJB object.

figure

Figure 2-2. EJB architecture

2.1.3.3. Deploying a bean

The EJB object and EJB home are generated during the deployment process. After the files that define the bean (the home interface, the remote interface, and the bean classes) have been packaged into a JAR file, the bean is ready to be deployed: that is, added to an EJB container so that it can be accessed as a distributed component. During the deployment process, tools provided by the EJB container vendor generate the EJB object and EJB home classes by examining the deployment descriptor and the other interfaces and classes in the JAR file.



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.