[ Team LiB ] Previous Section Next Section

EJB Implementation

So far, we've looked at the different types of EJBs as defined by the specification along with the list of services the EJB container offers. Now let's look at what constitutes an enterprise bean. An Enterprise JavaBean is not a single class. An enterprise bean consists of a set of Java files along with a set of XML files that contain the deployment descriptors describing the enterprise bean. For implementing a Session or Entity bean, the EJB developer has to define the component interfaces, the home interface, and a bean class. In the case of Entity beans, the EJB developer could also define a primary key class. Message-Driven beans are different from the Session and Entity bean types in that they require only the bean class and have no need for interfaces.

The Bean Class

All bean types' bean class implements specialized interfaces that extend from the javax.ejb.EnterpriseBean interface. Table 20.3 defines the base classes for the different bean types.

Table 20.3. Bean Types and Their Base Interfaces

Bean Type

Base Interface for the Bean Class

Session Bean

javax.ejb.SessionBean

Entity Bean

javax.ejb.EntityBean

Message-Driven Bean

javax.ejb.MessageDrivenBean

Figure 20.4 describes the class hierarchy for the bean classes listed in Table 20.2. The Session and Entity bean classes define the bean's business methods and also define the life cycle–related methods; for example, create, remove, and so on. The bean class should implement all the methods defined in the component interfaces. The bean class doesn't implement the home or component interfaces directly. The method signatures should match exactly with business methods defined in the home and component interfaces, and should have methods corresponding to non-business methods (for example, life cycle methods such as create, remove, and so forth) in all interfaces. This is because the EJB compiler generates the objects that actually implement the remote home and remote interfaces.

Figure 20.4. Bean class hierarchy.

graphics/20fig04.gif

Because the container automatically invokes Message-Driven beans to process JMS requests, these beans implement only the bean class base interface. The home and component interfaces do not apply to Message-Driven beans. A Message-Driven bean implements javax.jms.MessageListener apart from javax.ejb.MessageDrivenBean. The MessageListener interface defines only one method, onMessage(), to handle the JMS requests. The container invokes this method automatically. In the future, the specification might address Message-Driven beans handling other kinds of messages.

Remote Interface

The remote interface provides access to the bean's business methods to clients that use the bean. This interface extends from the javax.ejb.EJBObject interface, which in turn extends from the java.rmi.Remote interface for providing remote connectivity. Figure 20.5 describes the class hierarchy for the remote interface. It contains two sample beans: a Trader Session bean and an Account Entity bean. This interface works with the remote home interface of a bean to provide services to other applications.

Figure 20.5. Remote interface hierarchy.

graphics/20fig05.gif

EJB Object—javax.ejb.EJBObject

Now let's examine the interface javax.ejb.EJBObject from which all bean types' remote interface are extended. This provides the functionality that enables us to use our remote interface over the network using RMI. Apart from this, the EJBObject interface provides the client with some very useful methods that describe the bean:

  • The getEJBHome method on this interface returns a handle to the remote home interface of the bean from which the remote object was obtained. Remote home interfaces are returned as the base type: javax.ejb.EJBHome. This interface can then be narrowed to the appropriate type and used. This method is useful when your design moves the remote interface of the bean outside the context in which it has been created. For instance, if you pass the remote interface as a parameter to a method, and the method requires the remote home interface, it can access the remote home interface by invoking this method. This method isn't very useful for the client because the client has the bean's home when it calls a method on that bean, but it provides completeness of EJB's metadata.

  • The getHandle method returns an object of type javax.ejb.Handle. This object is a serializable representation of the remote interface. The client object can serialize this handle and store it for later use. When it again requires access to a remote method, the object can now call the getEJBObject method on the handle, as long as the Session bean is still available in the container that generated the handle. If the bean is no longer available, the getEJBObject method throws an exception of type RemoteException. The only exclusion to this rule is Stateless Session beans because they aren't linked to a single client. This method returns an object that can be cast to the remote interface. When the remote interface has been obtained, the client object can continue to invoke the business methods.

  • The isIdentical method returns a Boolean indicating whether the EJBObject passed as a parameter is identical to the one on which the method is being invoked. Two Stateless Session beans of the same type (that is, their originator home objects come from the same location) are always identical because there is conceptually no difference between the outcomes of an operation on two bean objects of the same type. Therefore, in this one case, this method will always return true. It will also return true when comparing two Entity beans with the same primary key. Note that even when the isIdentical method returns true for two objects, the Object.equal method might not. This is because, the network-related information that's stored in the EJBObject stubs might not match, and the equal method would therefore return false. Using the isIdentical method will ignore network-related fields and return the correct result. Additionally, it's good to note that it isn't sufficient that the EJB stub and instance are of the same class—the same home stub must also obtain them. If a single session bean is deployed twice in two different JNDI locations, they will not be identical.

  • The remove method removes the bean object. For Stateless Session beans, the bean object is not necessarily physically deleted by invoking this method. It might simply be returned to the free pool of bean objects (known as the method-ready pool) as illustrated in Figure 20.3. If the client tries to invoke any business method on the remote interface after the remove method has been invoked, a java.rmi.NoSuchObjectException (a subclass of RemoteException) is thrown. For Stateful Session beans, the instance is destroyed. For Entity beans, the data is deleted and the bean instance is moved to the pool or destroyed.

  • Note also that the EJBObject contains one other method: getPrimaryKey. A primary key is an object that uniquely identifies an Entity bean among all the available Entity beans. For the sake of this discussion, think of it as mirroring the primary key of the database, although that is not always the case. Thus, primary keys enable the client object to look up data from a persistent store. For more information on primary keys, see Chapter 22. Because Session beans don't have anything to do with persisted data, there is no concept of primary keys for Session beans. Hence, this method is irrelevant for Session beans. The EJBObject interface has this method declared in it because the remote interfaces of both Session and Entity beans extend from the interface EJBObject. If you try to invoke this method from a session bean, the method throws a RemoteException.

Home Interface

The home interface provides applications that want to use the bean access to the bean's life cycle methods. Figure 20.6 illustrates the class hierarchy of the home interface with two examples: TraderHome and AccountHome. Life cycle methods are those used to create new beans, remove existing ones, and find beans based on some criteria. The remote home interface is represented by the interface javax.ejb.EJBHome. The bean's remote home interface extends from this interface and provides access to appropriate methods. The EJBHome interface, in turn, extends from the java.rmi.Remote interface. This interface works along with the remote interface.

Figure 20.6. Home interface hierarchy.

graphics/20fig06.gif

Home Object

The remote home interface extends the EJBHome interface. This interface provides the remote access functionality to our remote home interface. Apart from this, the EJBHome interface also provides the client with some very useful methods that describe the bean.

  • The getHomeHandle method provided by this interface is very similar to the getHandle method of the EJBObject interface. This method returns a serializable representation of the remote home object. The object implements the interface javax.ejb.HomeHandle. The client can then serialize this form to other clients or for its own future use. When it needs to create another bean instance, it simply re-creates the home object by calling the getEJBHome method, which returns the home object that created the handle. This object can then be narrowed to the appropriate remote home object and the bean instances can be created.

  • The getEJBMetaData method returns the metadata that represents the bean. The metadata is returned in an object that implements the javax.ejb.EJBMetaData interface. We'll look at the components of the metadata that's returned in this object a little later in the chapter.

  • Two versions of the remove method are declared in this interface. The first version accepts a Handle object as its parameter. The Handle object is obtained by invoking the getHandle method on the remote object. The effect of invoking this method is the same as invoking the remove method on that remote object. When invoked, this method simply releases the Stateless Session bean to the container's free pool and makes it available for other clients. For Stateful Session beans, the bean is destroyed. For Entity beans, the data is deleted and the bean is sent to the pool or destroyed. After this point, if the client tries to use the remote object, a RemoteException is thrown. A second version of the remove method accepts a primary key as its parameter. As mentioned earlier, primary keys do not mean anything for session beans. Therefore, this method throws a RemoteException when invoked.

As mentioned, the getEJBMetaData method returns an object of type EJBMetaData. This object contains some very important pieces of information that describe the bean. This information is useful for development tools while building applications that use deployed EJBs. Clients that use scripting languages to access the beans can also benefit from this information.

  • The getEJBHome method returns the remote home object for the bean.

  • The getHomeInterfaceClass method returns a Class that represents the remote home interface of the bean.

  • The getRemoteInterfaceClass method returns a Class that represents the remote interface of the bean.

  • The isSession method tests whether the bean is a Session bean and returns a boolean indicating the result of the test.

  • The isStatelessSession method tests whether the bean is a Stateless Session bean and returns a boolean indicating the same.

  • The getPrimaryKeyClass method returns the class that represents the primary key for Entity beans. For Session beans, this method should not be invoked because a primary key does not mean anything to a Session bean. If the method is invoked, it throws a RuntimeException.

Table 20.4 lists the values returned by the two functions—namely, isStatelessSession and isSession—related to identifying bean types based on the available session.

Table 20.4. Bean Types

Bean Type

isStatelessSession()

isSession()

Stateless Session Bean

true

true

Stateful Session Bean

false

true

Entity Bean

false

false

Message-Driven Bean

Not applicable (no home)

Not applicable (no home)

Local and Local Home Interfaces

If the local home interface of the bean extends from the interface javax.ejb.EJBLocalHome instead of the javax.ejb.EJBHome interface, other beans residing within the same container can efficiently use the bean. This interface offers similar bean life cycle methods as those offered by the remote home interface. The difference between the two is that when beans are created using this interface, no network connectivity is involved because both the requested and the requestor exist within the same container. This drastically improves performance for such local access. This interface works in conjunction with the local home interface.

The local interface of a bean is similar to the remote interface in that this interface also provides access to the business methods provided by the bean class. This interface works with the local home interface to provide access to the bean instance for other beans within the same container. All method calls made using this interface avoid network protocols, and thus improve performance. The local interface of a bean extends the javax.ejb.EJBLocalObject interface.

The same bean may provide both local and remote access, or just any one of them, by including the appropriate set of home and object interfaces in its deployment descriptor. There is a downside to using local interfaces: It reduces the location transparency of the beans. So, if you're sure that the objects will always colocate, give preference to using local interfaces.

TIP

Remote access involves passing parameters by value (copying), whereas local access involves passing them by reference (sharing). If a bean tries to modify its parameters and you switch its access from local to remote (or vice versa), the results are unpredictable. To avoid being trapped, do not modify parameters.


The local component interfaces have been optimized in such a way that any call made using a local interface is made as if it were just another call to any other object on the JVM. This means that with local interfaces, there is no requirement for the parameter objects to be serializable and they are passed by reference to the bean.

The local interface provides similar methods as the remote interface. There are a couple of differences between these two interfaces. All other methods provided by the EJBObject interface are also provided by the EJBLocalObject interface and behave in exactly the same way. We'll list only the differences between the two interfaces here.

  • The method getEJBHome in the EJBObject interface is not available in the EJBLocalObject interface. Instead, this interface declares another method, called getEJBLocalHome, which returns the local home as an object of type EJBLocalHome. This object may then be cast into the appropriate local home and used.

  • Unlike the EJBObject interface, the EJBLocalObject interface does not define a getHandle method. Because serialization is not required between collocated objects, this method does not make sense.

  • None of the methods throw RemoteExceptions.

The EJBLocalHome interface, unlike the EJBHome interface, has just a single remove method that takes a primary key as its parameter. Needless to say, this method cannot be invoked for Session beans. If it is, the method throws a RemoveException.

Primary Key

This is a special class that pertains only to Entity bean implementations. It provides an identifier for the database record that the Entity bean represents. This class has to implement java.io.Serializable. This class will be used in the finder method (findByPrimaryKey() method) of the home interface to locate the specific entity. This is covered in detail in the chapter on Entity beans (see Chapter 22, "Working with Entity Beans").

EJB Exceptions

Because EJBs conform to RMI-IIOP standard, all methods in the remote EJB object and remote home interface have to throw remote exceptions (java.rmi.RemoteException). Remote exceptions indicate a network failure or other fatal situations. But the local interfaces and local home are different from the remote counter parts in that they don't throw remote exceptions at all. This is quite obvious because no network functionality is involved when using local interfaces.

EJB separates system-level exceptions from application exceptions. A system-level exception might include fatal situations such as a database failure, a server crash, and so on. The generated implementation classes might handle these errors and provide transparent failover in some cases (such as a server crash) by moving to another bean deployed in the clustered server. All application exceptions are always thrown back to the client. The application exceptions include bean-defined exceptions such as FinderException and CreateException as well as business exceptions.

EJB Naming Conventions

Let's establish some naming conventions to provide clarity for our discussion of EJBs in the next three chapters. We look at these conventions with the help of one of the real-world examples: an airline reservation system that we use as a business case to explain the session beans in the next chapter. Although we speak about an EJB as a whole, we'll refer to it using its business name with the suffix EJB. For example, AirlineReservationEJB and AirlineReservation EJB. This identifies the EJB as a whole and not the bean class alone. That is, you won't find a file called AirlineReservationEJB.java. Instead that name refers to a set of .java files. Similarly, when we refer to a Session bean, or just a bean, we're referring to the bean as a whole, which includes all constituents as listed in the previous sections. This goes for Entity beans and Message-Driven beans.

When naming a Bean class, we'll use its business name with the suffix Bean; for example, AirlineReservationBean. We'll also distinguish between the different types of interfaces by using appropriate suffixes. A remote home interface will be referred to using the business name of the bean along with the suffix RemoteHome. For example, the remote home interface for the AirlineReservation EJB is called AirlineReservationRemoteHome. On the other hand, a local home interface will hold the suffix LocalHome to distinguish it from the remote counterpart (for example, AirlineReservationLocalHome). A remote interface will be denoted with the business name and the suffix RemoteObject, whereas its local object counterpart will have the suffix Local appended to the business name. For example, AirlineReservationRemoteObject denotes a remote interface for the AirlineReservation EJB, whereas AirlineReservationLocalObject denotes its local interface.

Note also that when we refer to a client in our discussion, we aren't necessarily referring to a user interface unless it is explicitly specified. We're referring to any object that uses the EJB—the client to the bean.

    [ Team LiB ] Previous Section Next Section