The ejbFind( ) Methods

In bean-managed persistence, the find methods in the remote or local home interface must match the ejbFind( ) methods in the actual bean class. In other words, for each method named find< SUFFIX >( ) in a home interface, there must be a corresponding ejbFind< SUFFIX >( ) method in the entity bean class with the same arguments and application exceptions. When a find method is invoked on an EJB home, the container delegates the find( ) method to a corresponding ejbFind( ) method on the bean instance. The bean-managed entity is responsible for locating records that match the find requests. There are two find methods in ShipHomeRemote:

public interface ShipHomeRemote extends javax.ejb.EJBHome {

    public ShipRemote findByPrimaryKey(Integer primaryKey) 
        throws FinderException, RemoteException;
    public Collection findByCapacity(int capacity) 
        throws FinderException, RemoteException;
}

Here are the signatures of the corresponding ejbFind( ) methods in the ShipBean:

public class ShipBean implements javax.ejb.EntityBean {

    public Integer ejbFindByPrimaryKey(Integer primaryKey) 
        throws FinderException {}
    public Collection ejbFindByCapacity(int capacity) 
        throws FinderException {}
}

Aside from the names, there’s a significant difference between these two groups of methods. The find methods in the home interface return either an EJB object implementing the bean’s remote interface—in this case, ShipRemote--or a collection of EJB objects in the form of a java.util.Enumeration or java.util.Collection. The ejbFind( ) methods in the bean class, on the other hand, return either a primary key for the appropriate bean—in this case, Integer—or a collection of primary keys. The methods that return a single value (whether a remote/local interface or a primary key) are used whenever you need to look up a single reference to a bean. If you are looking up a group of references (for example, all ships with a certain capacity), you have to use the method that returns either the Collection or Enumeration type. In either case, the container intercepts the primary keys and converts them into remote references for the client.

Tip

The EJB specification recommends that bean-managed persistence beans use the Collection type instead of the Enumeration type. This recommendation is made so that BMP beans are more consistent with CMP beans, which use only the Collection type. The Enumeration type is an artifact of EJB 1.0 and 1.1 and is maintained for backwards compatibility.

It shouldn’t come as a surprise that the type returned—whether it’s a primary key or a remote (or local) interface—must be appropriate for the type of bean you’re defining. For example, you shouldn’t put find methods in a Ship EJB to look up and return Cabin EJB objects. If you need to return collections of a different bean type, use a business method in the remote interface, not a find method from one of the home interfaces.

The EJB container takes care of returning the proper (local or remote) interface to the client. For example, the Ship EJB may define a local and a remote home interface, both of which have a findByPrimaryKey( ) method. When findByPrimary( ) is invoked on the local or remote interface, it will be delegated to the ejbFindByPrimary( ) key method. After the ejbFindByPrimaryKey( ) method executes and returns the primary key, the EJB container takes care of returning a ShipRemote or ShipLocal reference to the client, depending on which home interface (local or remote) was used. The EJB container also handles this for multi-entity find methods, returning a collection of remote references for remote home interfaces or local references for local home interfaces.

Both find methods defined in the ShipBean class throw an EJBException if a failure in the request occurs when an SQL exception condition is encountered. findByPrimaryKey( ) throws an ObjectNotFoundException if no records in the database match the id argument. This is exception should always be thrown by single-entity find methods if no entity is found.

The findByCapacity( ) method returns an empty collection if no SHIP records with a matching capacity are found; multi-entity find methods do not throw ObjectNotFoundExceptions if no entities are found.

It is mandatory for all entity remote and local home interfaces to include the findByPrimaryKey( ) method. This method returns the remote or local interface type (ShipRemote or ShipLocal). It declares one parameter, the primary key for that bean type. With local home interfaces, the return type of any single-entity finder method is always the bean’s local interface. With remote home interfaces, the return type of any single-entity find method is the remote interface. You cannot deploy an entity bean that doesn’t include a findByPrimaryKey( ) method in its home interfaces.

Following the rules outlined earlier, we can define two ejbFind( ) methods in ShipBean that match the two find( ) methods defined in the ShipHomeRemote:

public Integer ejbFindByPrimaryKey(Integer primaryKey) throws FinderException {
    Connection con = null;
    PreparedStatement ps = null;
    ResultSet result = null;
    try {
        con = this.getConnection( );
        ps = con.prepareStatement("select id from Ship where id = ?");
        ps.setInt(1, primaryKey.intValue( ));
        result = ps.executeQuery( );
        // Does the ship ID exist in the database?
        if (!result.next( )) {
            throw new ObjectNotFoundException("Cannot find Ship with id = "+id);
        }
    } catch (SQLException se) {
        throw new EJBException(se);
    }
    finally {
        try {
            if (result != null) result.close( );
            if (ps != null) ps.close( ); 
            if (con!= null) con.close( ); 
        } catch(SQLException se) {
            se.printStackTrace( );
        }
    }
    return primaryKey;
}
public Collection ejbFindByCapacity(int capacity) throws FinderException {
    Connection con = null;
    PreparedStatement ps = null;
    ResultSet result = null;        
    try {
        con = this.getConnection( );
        ps = con.prepareStatement("select id from Ship where capacity = ?");
        ps.setInt(1,capacity);
        result = ps.executeQuery( );
        Vector keys = new Vector( );
        while(result.next( )) {
            keys.addElement(result.getObject("id"));
        }
        return keys;
    }
    catch (SQLException se) {
        throw new EJBException (se);
    }
    finally {
        try {
            if (result != null) result.close( );
            if (ps != null) ps.close( ); 
            if (con!= null) con.close( ); 
        } catch(SQLException se) {
            se.printStackTrace( );
        }
    }      
}

The mandatory findByPrimaryKey( ) method uses the primary key to locate the corresponding database record. Once it has verified that the record exists, it simply returns the primary key to the container, which then uses the key to activate a new instance and associate it with that primary key at the appropriate time. If no record is associated with the primary key, the method throws an ObjectNotFoundException.

The ejbFindByCapacity( ) method returns a collection of primary keys that match the criteria passed into the method. Again, we construct a prepared statement that we use to execute our SQL query. This time, however, we expect multiple results, so we use the java.sql.ResultSet to iterate through the results, creating a vector of primary keys for each SHIP_ID returned.

Find methods are not executed on bean instances that are currently supporting a client application. Only bean instances that are not currently assigned to an EJB object (i.e., instances in the instance pool) are supposed to service find requests, which means that the ejbFind( ) methods in the bean instance have somewhat limited use of the EntityContext. The EntityContext methods getPrimaryKey( ) and getEJBObject( ) will throw exceptions because the bean instance is in the pool and is not associated with a primary key or EJB object when the ejbFind( ) method is called.

Where do the objects returned by find methods originate? This seems like a simple enough question, but the answer is surprisingly complex. Remember that find methods aren’t executed by bean instances that are actually supporting the client; rather, the container selects an idle bean instance from the instance pool to execute the method. The container is responsible for creating the EJB objects and local or remote references for the primary keys returned by the ejbFind( ) method in the bean class. As the client accesses these remote references, bean instances are swapped into the appropriate EJB objects, loaded with data, and made ready to service the client’s requests.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.124.21