Read all about EJB 2.0

Dramatic EJB 2.0 changes enhance flexibility and portability in your application development

Enterprise JavaBeans 2.0, released June 2, is not just a point release but also a new version of the specification. At just over 500 pages, the EJB 2.0 specification is 200 pages (66 percent) longer than the previous EJB 1.1 specification. The most important changes in the specification are those made to container-managed persistence (CMP) and the introduction of a completely new bean type, the MessageDrivenBean.

The bulk of the changes in EJB 2.0 are found in the definition of a new CMP component model. It's radically different from the old CMP model because it introduces an entirely new participant, the persistence manager, and a completely new way of defining container-managed fields, as well as relationships with other beans and dependent objects.

The introduction of the MessageDrivenBean (the message bean) is also significant. The message bean represents the integration of JMS (Java Message Service) with EJB to create an entirely new type of bean designed to handle asynchronous JMS messages. That exciting new bean type provides a component model for JMS clients, allowing them to be deployed in the rich and robust environment of an EJB container system.

There are many other smaller changes made to the specification. Those other changes, while important, are mostly concerned with tightening the specification to eliminate ambiguities and make the components more portable. This article focuses on the new CMP and message bean component models introduced in EJB 2.0.

I provide several concrete examples, so it should be fairly easy to follow and comprehend. EJB novices might, however, find the material more difficult since it's assumed that readers have a basic understanding of EJB. For more information on EJBs, please see Resources.

Container-managed persistence

Container-managed persistence has undergone radical changes in EJB 2.0. In EJB 2.0, the persistence manager handles persistence of CMP entity beans automatically at runtime. The persistence manager is responsible for mapping the entity bean to the database based on a new bean-persistence manager contract called the abstract persistence schema. In addition, the persistence manager is responsible for implementing and executing find methods based on a new query language called EJB QL.

It's important to note that products that comply with the EJB 2.0 specification must support the EJB 1.1 CMP model as well as the new EJB 2.0 model. While those models are not compatible, support is required for the EJB 1.1 model to ensure backward compatibility.

The abstract persistence schema

To understand how the abstract persistence schema works and why it's important, I will quickly review for you how CMP is handled in EJB 1.1, and then discuss how it's defined in EJB 2.0.

The EJB 1.1 CMP model

In EJB 1.1, the bean developer is responsible for declaring the bean class' persistent fields as either Java primitive or serializable types. The following examples show an Employee enterprise bean class, as defined in EJB 1.1, with several CMP fields:

// the Employee bean class
public class EmployeeBean implements java.ejb.EntityBean {
    // instance fields
    EntityContext ejbContext;
 
    // container-managed fields
    public int identity;
    public String firstName;
    public String lastName;
    public double salary;
    public Address address;
    public Integer ejbCreate(int id, String fname, String lname){
        identity = id;
        firstName = fname;
        lastName = lname;
        return null;
    }
    ...
}
// The Address dependent class
public class Address implements Serializable{
           public String street;
           public String city;
           public String state;
           public String zip;
}

When a relational database is used for persistence, the primitive fields such as identity, firstName, lastName, and salary are fairly easy to persist since they map nicely to SQL types such as INTEGER, CHAR, and DOUBLE.

In EJB 1.1, the XML deployment descriptor of a CMP bean provides cmp-field elements for identifying the persistent fields (container-managed fields) in the bean class. As shown below, the cmp-field elements are used to differentiate between the fields that are written to the database and those that are not. For example, the ejbContext field is not included in the list of container-managed fields and is therefore not a persistent field.

<ejb-jar>
   <enterprise-beans>
      <entity>
             <ejb-name>EmployeeEJB</ejb-name>
             ...
             <persistence-type>Container</persistence-type>
             ...
             <cmp-field><field-name>identity</field-name></cmp-field>
             <cmp-field><field-name>firstName</field-name></cmp-field>
             <cmp-field><field-name>lastName</field-name></cmp-field>
             <cmp-field><field-name>salary</field-name></cmp-field>
             <cmp-field><field-name>address</field-name></cmp-field>
             ...

The container provider supplies a tool for mapping the bean's persistent fields to the columns in the database tables, usually one table per bean. Serializable types such as Address, however, are more difficult to persist. In EJB 1.1 there is no standard way of mapping serializable objects to a relational database. Although the Address class has its own set of fields, the XML deployment descriptor doesn't provide a mechanism for mapping those fields to the database. In most cases it was expected that serializable objects such as Address would be persisted as a binary type, which is sometimes called a blob type, to a database table.

That problem is exacerbated as the entity bean's data schema grows in complexity. An Employee bean, for example, might have many child objects similar to Address, such as Benefits and JobPosition. Those child objects, called dependent objects, can form complex object graphs spanning several tables in a relational database. In addition, CMP in EJB 1.1 is largely inadequate for persisting relationships with other beans. In EJB 1.1, if a bean was to maintain a relationship with another bean, the container would automatically use the primary key or handle as a link. That has proven to be a fairly crude mechanism for maintaining relationships with other beans whose natural relationship may be bidirectional or dependent on fields not easily represented by the primary key or handle.

The EJB 2.0 CMP model

In EJB 2.0, a new contract between the CMP entity bean and persistence manager lets you define more complex and portable bean-to-bean, bean-to-dependent, and even dependent-to-dependent object relationships within an entity bean.

The persistent manager is a new participant in the Enterprise JavaBeans deployment process. The container vendor or a vendor that specializes in persistence to a particular database may provide the persistence manager. The idea is to separate the mechanism used to manage bean relationships from the container, which is responsible for managing security, transactions, and resources. The separation of responsibilities allows different persistence managers to work with different containers. It also allows entity beans to become more portable across EJB vendors as well as persistence managers.

If you have worked with or studied CocoBase, a product from Thought Inc. that automatically generates BMP (Bean Managed Persistence) beans for EJB 1.1 containers, then you are already somewhat familiar with how a persistent manager tool might work. CocoBase generates all the database access logic for BMP beans based on object-to-relational mapping information provided by the bean deployer. In EJB 2.0, the persistence manager can generate a mapping of CMP entities to a relational database based on information provided by the deployment descriptor, the bean's abstract persistence schema, and work performed by the deployer. The persistence manager is not, however, limited to a relational database. Persistence managers may also be developed for object databases as well as legacy and ERP systems such as SAP.

In order for the persistence manager to be separated from the container, a contract between the bean and the persistence manager had to be defined. The contract is manifested in the new abstract persistence schema. That schema is defined through a new set of XML elements in the deployment descriptor and a set of code idioms in the CMP entity beans. In EJB 2.0, the CMP bean class is declared as abstract and its persistent and relationship fields are accessed using abstract accessor and mutator methods whose method signatures map to special elements in the XML deployment descriptor.

When the bean is deployed, you will use persistent manager tools to generate a concrete implementation of the abstract bean class and its dependent object classes based on the XML deployment descriptor and the bean class. The concrete implementations will include the data access code that will actually read and write the bean's state to the database at runtime. At runtime, the container uses the subclasses generated by the persistence manager tools instead of the abstract classes defined by the bean provider.

Inheritance hierarchy of a bean class

To give some meat to the discussion, a CMP entity example is provided that explains more concretely how the abstract persistence schema works.

An example CMP entity in EJB 2.0

In EJB 2.0 a container-managed entity bean is defined to be abstract and its persistent fields are not defined directly in the bean class. Instead, an abstract persistent schema has been developed that lets the bean provider declare the persistent fields and bean relationships indirectly. Below is an example of the Employee bean that uses the new abstract persistent schema. Notice that none of the persistent fields are declared in the bean class.

public abstract EmployeeBean implements javax.ejb.EntityBean {
  .  // instance fields
     EntityContext ejbContext;
     // container-managed persistent fields
           public abstract void setIdentity(int identity);
           public abstract int getIdentity();
           public abstract void setFirstName(String firstName);
           public abstract String getFirstName();
           public abstract void setLastName(String lastName);
           public abstract String getLastName();
           
     // container-managed relationship fields
           public abstract void setContactInfo(ContactInfo info);
           public abstract ContactInfo getContactInfo();
            
...
}

In the XML deployment descriptor of that bean, the abstract persistence schema declares the container-managed fields and relationships.

<ejb-jar>
  <enterprise-beans>
        <entity>
             <ejb-name>EmployeeEJB</ejb-name>
             ...
             <persistence-type>Container</persistence-type>
             ...
             <cmp-field><field-name>identity</field-name></cmp-field>
             <cmp-field><field-name>firstName</field-name></cmp-field>
             <cmp-field><field-name>lastName</field-name></cmp-field>
             ...
        </entity>
   </enterprise-beans>
   <dependents>
      <dependent>
            <dependent-class>ContactInfo</dependent-class>
            <dependent-name>ContactInfo</dependent-name>
            <cmp-field>street</cmp-field>
            <cmp-field>city</cmp-field>
            <cmp-field>state</cmp-field>
            <cmp-field>zip</cmp-field>
           <cmp-field>homePhone</cmp-field>
           <cmp-field>workPhone</cmp-field>
           <cmp-field>email</cmp-field>
           ...
      </dependent>
      <relationships>
          <ejb-relation>
              <ejb-relation-name>Employee-ContactInfo</ejb-relation-name>
              <ejb-relationship-role>
                    <ejb-relationship-role-name>
                                    employee-has-contactinfo
                    </ejb-relationship-role-name>
                    <multiplicity>one</multiplicity>
                    <role-source>
                          <ejb-name>EmployeeEJB</ejb-name>
                    </role-source>
                   <cmr-field>
                          <cmr-field-name>contactInfo</cmr-field-name>
                          <cmr-field-type>ContactInfo</cmr-field-type>
                  </cmr-field>
           </ejb-relationship-role>
          <ejb-relationship-role>
                   <ejb-relationship-role-name>
                          contactinfo_belongsto_employee
                   </ejb-relationship-role-name>
                   <multiplicity>one</multiplicity>
                   <role-source>
                             <dependent-name>ContactInfo<dependent-name>
                   </role-source>
            </ejb-relationship-role>
       </ejb-relation>
   </relationships>
<ejb-jar>
1 2 3 4 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more