ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button O'Reilly Book Excerpts: Enterprise JavaBeans, 4th Edition

Developing Your First Enterprise Beans, Part 1

by Bill Burke, Richard Monson-Haefel, and Sacha Labourey

One of the most important features of EJB is that enterprise beans have the ability to work with containers from different vendors. However, that doesn't mean that selecting a server and installing your enterprise beans on that server are trivial processes.

Related Reading

Enterprise JavaBeans
By Richard Monson-Haefel, Bill Burke, Sacha Labourey

Choosing and Setting Up an EJB Server

The EJB server you choose should provide a utility for deploying enterprise beans. It doesn't matter whether the utility is command-line oriented or graphical, as long as it does the job. The deployment utility should allow you to work with prepackaged enterprise beans, i.e., enterprise beans that have already been developed and archived in a JAR file. Finally, the EJB server must support an SQL-standard relational database that is accessible using JDBC. For the database, you should have privileges sufficient for creating and modifying a few simple tables in addition to normal read, update, and delete capabilities. If you have chosen an EJB server that does not support a SQL-standard relational database, you may need to modify the examples to work with the product you are using.

This book does not say very much about how to install and deploy enterprise beans. That task is largely server-dependent. We'll provide some general ideas about how to organize JAR files and create deployment descriptors, but for a complete description of the deployment process, you'll have to refer to your vendor's documentation.

Setting Up Your Java IDE

To get the most from this chapter, it helps to have anIDE that has a debugger and allows you to add Java files to its environment. Several Java IDEs - such as BEA's Weblogic Workshop, IBM'sEclipse, Borland's JBuilder, and Sun'sForte - fulfill this requirement. Some EJB products, such as IBM'sWebSphere and BEA's Weblogic, are tightly coupled with an IDE that makes life a lot easier when it comes to writing, deploying, and debugging your applications.

Once you have an IDE set up, you need to include the Enterprise JavaBeans and other J2EE packages which will be provided by your application server vendor - usually in a single JAR file (e.g., j2ee.jar).

Developing an Entity Bean

There's no better place to start than the Cabin EJB, which we have been examining throughout the previous chapters. The Cabin EJB is an entity bean that encapsulates the data and behavior associated with a cruise ship cabin in Titan's business domain.

Cabin: The Remote Interface

When developing an entity bean, we first want to define its remote interface. The remote interface defines the bean's business purpose; the methods of this interface must capture the concept of the entity. We defined the remote interface for the Cabin EJB in Chapter 2; here, we add two new methods for setting and getting the ship ID and the bed count. The ship ID identifies the ship to which the cabin belongs, and the bed count tells how many people the cabin can accommodate:

package com.titan.cabin;

import java.rmi.RemoteException;

public interface CabinRemote 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;
    public int getShipId( ) throws RemoteException;
    public void setShipId(int sp) throws RemoteException;
    public int getBedCount( ) throws RemoteException;
    public void setBedCount(int bc) throws RemoteException; 
}

The CabinRemote interface defines four properties: name, deckLevel, shipId, and bedCount. Properties are attributes of an enterprise bean that can be accessed by public set and get methods.

Notice that we have made the CabinRemote interface a part of a new package named com.titan.cabin. Place all the classes and interfaces associated with each type of bean in a package specific to the bean. Because our beans are for the use of the Titan cruise line, we placed these packages in the com.titan package hierarchy. We also created directory structures that match package structures. If you are using an IDE that works directly with Java files, create a new directory called dev (for development) and create the directory structure shown in Figure 4-1. Copy the CabinRemote interface into your IDE and save its definition to the cabin directory. Compile the CabinRemote interface to ensure that its definition is correct. The CabinRemote.class file, generated by the IDE's compiler, should be written to the cabin directory, the same directory as the CabinRemote.java file. The rest of the Cabin bean's classes will be placed in this same directory.

Figure 4-1
Figure 4-1. Directory structure for the Cabin bean

CabinHome: The Remote Home Interface

Once we have defined the remote interface of the Cabin EJB, we have defined the remote view of this simple entity bean. Next, we need to define the Cabin EJB's remote home interface, which specifies how the enterprise bean can be created, located, and destroyed by remote clients; in other words, the Cabin EJB's life-cycle behavior. Here is a complete definition of the CabinHomeRemote home interface:

package com.titan.cabin;

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

public interface CabinHomeRemote extends javax.ejb.EJBHome {

    public CabinRemote create(Integer id) 
        throws CreateException, RemoteException;

    public CabinRemote findByPrimaryKey(Integer pk) 
        throws FinderException, RemoteException;
}

The CabinHomeRemote interface extends javax.ejb.EJBHome and defines two life-cycle methods: create( ) and findByPrimaryKey( ). These methods create and locate remote references to Cabin EJBs. Remove methods (for deleting enterprise beans) are defined in the javax.ejb.EJBHome interface, so the CabinHomeRemote interface inherits them.

CabinBean: The Bean Class

We have now defined the remote client-side API for creating, locating, using, and removing the Cabin EJB. Now we need to define CabinBean, the class that provides the implementation on the server for the Cabin EJB. The CabinBean class is an entity bean that uses container-managed persistence, so its definition will be fairly simple.

In addition to the callback methods discussed in Chapter 2 and Chapter 3, we must also define accessor methods for the CabinRemote interface and an implementation of the create method defined in the CabinHomeRemote interface. Here is the complete definition of the CabinBean class:

package com.titan.cabin;

import javax.ejb.EntityContext;

public abstract class CabinBean implements javax.ejb.EntityBean {

    public Integer ejbCreate(Integer id){
        this.setId(id);
        return null;
    }
    public void ejbPostCreate(Integer id){
      
    }
    public abstract void setId(Integer id);
    public abstract Integer getId( );
 
    public abstract void setShipId(int ship);
    public abstract int getShipId( );

    public abstract void setName(String name);
    public abstract String getName( );

    public abstract void setBedCount(int count);
    public abstract int getBedCount( );

    public abstract void setDeckLevel(int level);
    public abstract int getDeckLevel( );

    public void setEntityContext(EntityContext ctx) {
        // Empty implementation.
    }
    public void unsetEntityContext( ) {
        // Empty implementation.
    }
    public void ejbActivate( ) {
        // Empty implementation.
    }
    public void ejbPassivate( ) {
        // Empty implementation.
    }
    public void ejbLoad( ) {
        // Empty implementation.
    }
    public void ejbStore( ) {
        // Empty implementation.
    }
    public void ejbRemove( ) {
        // Empty implementation.
    }
}

The CabinBean class can be divided into two sections for discussion: declarations for the container-managed fields and the callback methods.

Container-managed fields

The CabinBean defines several pairs of abstract accessor methods. For example, setName( ) and getName( ) are a pair of abstract accessor methods. These methods are responsible for setting and getting the entity bean's name field. When the bean is deployed, the EJB container automatically implements all the abstract accessor methods so that the bean state can be synchronized with the database. These implementations map the abstract accessor methods to fields in the database. Although all the abstract accessor methods have corresponding methods in the remote interface, CabinRemote, it's not necessary that they do so. Some accessor methods are for the entity bean's use only and are never exposed to the client through the remote or local interfaces. Note that, unlike the matching methods in the remote interface, the abstract accessor methods do not throw RemoteExceptions.

It's customary to consider the abstract accessor methods as providing access to virtual fields and to refer to those fields by their method names, less the get or set prefix. For example, the getName( )/setName( ) abstract accessor methods define a virtual container-managed persistence (CMP) field called name (the first letter is always changed to lowercase). The getDeckLevel( )/setDeckLevel( ) abstract accessor methods define a virtual CMP field called deckLevel, and so on.

The name, deckLevel, shipId, and bedCount fields represent the Cabin EJB's persistent state. They will be mapped to the database at deployment time. These fields are also publicly available through the entity bean's remote interface. Invoking the getBedCount( ) method on a CabinRemote EJB object causes the container to delegate that call to the corresponding getBedCount( ) method on the CabinBean instance.

There is no requirement that CMP fields must be exposed. The id field is another container-managed field, but its abstract accessor methods are not exposed to the client through the CabinRemote interface. This field is the primary key of the Cabin EJB; it's the entity bean's index to its data in the database. It's bad practice to expose the primary key of an entity bean - you don't want client applications to be able to change that key.

Pages: 1, 2, 3, 4

Next Pagearrow