Implementing a CMP Entity Bean

Specifying a CMP Entity bean is identical to specifying a BMP Entity bean; it consists of defining the local-home interface, the local interface, and the bean itself. The good news, as you saw in listing 7.1, is that the bean itself is significantly simpler (and quicker to implement).

The Local Interfaces

The requirements of local-home and local interfaces for a CMP Entity bean are the same as for a BMP Entity bean. In fact, if you are converting a BMP Entity bean to CMP you will probably not have to make any changes to the interfaces.

NOTE

The Agency case study has made changes to the findByLocation() methods in the Job and Applicant Entity beans. In the BMP version, the single parameter was a String. In the CMP version, the parameter must be a LocationLocal EJB reference to satisfy the requirement of CMR. The findByLocation() methods are used by the Message-Driven Beans to be discussed on Day 10.


For completeness, Listing 7.2 is the local-home interface of the Job bean and Listing 7.3 is the local interface.

Listing 7.2. JobLocalHome Interface
package data;

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

public interface JobLocalHome extends EJBLocalHome
{
    JobLocal create (String ref, String customer) throws CreateException;
    JobLocal findByPrimaryKey(JobPK key) throws FinderException;
    Collection findByCustomer(String customer) throws FinderException;
    Collection findByLocation(LocationLocal location) throws FinderException;
    void deleteByCustomer(String customer);
}

Listing 7.3. JobLocal Interface
package data;

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

public interface JobLocal extends EJBLocalObject
{
    String getRef();
    String getCustomer();

    void setDescription(String description);
    String getDescription();

    void setLocation(LocationLocal location);
    LocationLocal getLocation();

    Collection getSkills();
    void setSkills(Collection skills);
}

Just as for BMP Entity beans, implementing a CMP Entity bean involves providing an implementation for the methods of the javax.ejb.EntityBean interface, corresponding methods for each method in the home interface, and a business method for each method in the local/remote interface.

Implementing javax.ejb.EntityBean

In this section, you will implement the CMP version of the Job Entity bean that was shown previously in Listing 7.1—the same bean was also used on Day 6 when studying BMP Entity beans.

With CMP, the field access and modifier methods must be provided as abstract functions. The EJB container will provide implementations for these methods:

// CMP fields
public abstract String getRef ();
public abstract void setRef (String ref);
public abstract String getCustomer ();
public abstract void setCustomer (String customer);
public abstract String getDescription ();
public abstract void setDescription(String description);

// CMR fields
public abstract LocationLocal getLocation ();
public abstract void setLocation(LocationLocal location);
public abstract Collection getSkills();

public abstract void setSkills(Collection skills);

The Job bean must define setter methods for the Ref and Customer properties, even though these are not defined in the local interface. Without these abstract setter definitions, the fields cannot be managed using CMP (as discussed later when describing the ejbCreate() method).

Because the bean contains abstract methods, the bean class must also be abstract, as well as extend javax.ejb.EntityBean:

public abstract class JobBean implements EntityBean {...}

A CMP Entity bean will have to provide implementations of any business methods that do not correspond to CMP or CMR fields in the bean. The Job bean has no additional business methods in the local interface.

The Job bean does have a single business method in the home interface—namely the deleteByCustomer() method for deleting jobs for a specific customer. An EJB Entity bean (just like a BMP bean) must provide an implementation of this method in ejbHomeDeleteByCustomer() as follows:

public void ejbHomeDeleteByCustomer(String customer)
            throws FinderException, RemoveException {
    Collection jobs = ((JobLocalHome)ctx.getEJBLocalHome()).findByCustomer(customer);
    for (Iterator iter = jobs.iterator(); iter.hasNext(); ) {
        JobLocal job = (JobLocal)iter.next();
        iter.remove();
        job.remove();
    }
}

There is no need to provide implementations of the finder methods in the home interface, as these are defined in the deployment descriptor as described in the section “Deploying a CMP Entity Bean using J2EE RI.”

The ejbCreate() method simply persists the Entity bean data passed as parameters as follows:

public void ejbPostCreate (String ref, String customer) {}

public JobPK ejbCreate (String ref, String customer) throws CreateException {
    JobPK key = new JobPK(ref,customer);
    try {
        ((JobLocalHome)ctx.getEJBLocalHome()).findByPrimaryKey(key);
        throw new CreateException("Duplicate job name: "+key);
    }
    catch (FinderException ex) {}
    setRef(ref);
    setCustomer(customer);
    setDescription("");
    return null;
}

Note the use of setter methods to save the bean's state. This contrasts with the BMP equivalent where the fields were written to directly.

The implementation of this method would have been even shorter if the findByPrimaryKey() call, checking for duplicates, had been omitted. An alternative approach for the Job bean would be to rely on constraints in the underlying database to detect duplicate keys rather than explicitly make the test in the ejbCreate() method.

NOTE

Strictly, the appropriate exception to throw here is a DuplicateKeyException, not a CreateException. However, the EJB specification does not mandate this.


Under CMP, the bean should return null from the ejbCreate() method. The reason for this is that the EJB container can access the information that constitutes the primary key anyway, by virtue of the CMP fields.

Removing a bean requires no additional work so the ejbRemove() method is trivial:

public void ejbRemove() {}

CAUTION

The BMP version of ejbRemove() for Job bean resets all the fields to null. When implementing CMP Entity beans, you absolutely must not reset the fields to null. Doing so will cause the EJB container to throw an exception, because the bean's state is required so that the container can remove the correct data from the persistent data store. The ejbRemove() method is called before the data is deleted from the store.


Under CMP, the ejbLoad() and ejbStore() methods have nothing to do unless there is derived data to be maintained. The JobBean class has no additional work to do when data is retrieved and stored:

public void ejbLoad() {}
public void ejbStore() {}

The ejbLoad() method is called after the bean's state has been populated, so the bean's state can be read through the accessor methods. The ejbStore() method is called prior to saving the data to store.

The ejbActivate() and ejbPassivate() methods have nothing to do with storing data, so their implementation is unchanged:

public void ejbPassivate() {}
public void ejbActivate() {}

Under BMP, the setEntityContext() method was used to look up various bean home interfaces from JNDI, and also obtain the JDBC DataSource called java:comp/env/jdbc/Agency. These actions are no longer required as the EJB container maintains the persistent data. The revised EntityContext methods for the JobBean are:

private EntityContext ctx;

public void setEntityContext(EntityContext ctx) {
    this.ctx = ctx;
}

public void unsetEntityContext() {
    this.ctx = null;
}

The complete listing for the Job CMP Entity bean was shown in Listing 7.1 at the start of today's discussion.

Now that you have studied how to develop a CMP Entity bean you may be wondering why it is so easy. The answer is that the J2EE server vendor is doing a lot of work on your behalf. But the downside to this is that you will have to provide a lot more information in the deployment descriptors for your EJB. Of necessity, a lot of the extra information is platform-specific. To understand what additional information you need to supply you will now deploy the revised Job entity using the J2EE RI.

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

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