Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Container-managed relations for the 21st century

EJB 2.0's new relationship facilities assist developers in rapid deployment

Java developers often create complex relationships when they program applications to solve real-world business problems. Therefore, it was no surprise that when programmers began developing enterprise applications using Enterprise JavaBeans (EJB), they continued to describe their business models with complex relationships. In the original specification, EJBs, however, made such complex relationships more difficult because developers had little control over when an EJB was activated or passivated. In response, developers often wrote complex logic to ensure object persistence within these relationships.

Luckily, the EJB specification developers, recognizing the problem, added container-managed relationships (CMR) in EJB 2.0.

What are these relationships? How do you describe them? How do you encode them in your Java classes? In this article I answer those questions and others.

Note: I assume you understand Java and EJB. Although I give a CMP 2 (container-managed persistence) overview, you won't find an exhaustive CMP tutorial here. See Resources for more articles on EJB and CMP.

Also note: You can download this article's code examples from Resources.

CMP 2 overview

Before you can understand EJB relationships, you must first understand how EJBs work. How are their persistent fields defined? How do you define the relationships? What are the relationships' return objects?

The EJB 1.0 and 1.1 specifications identified container-managed fields by placing attributes in the bean, then described the fields in the deployment descriptor. Although other entity beans could reside within the parent entity bean, the container did not automatically handle their persistence or loading. The bean developer, therefore, had to write additional code, normally in the ejbCreate(), ejbActivate(), and ejbPassivate() methods to handle these additional entity beans. The developer, as his only alternative, could define entity beans using bean-managed persistence.

The EJB 2.0 specification changed the situation dramatically. Among the specification's many changes, container-managed fields now no longer have attributes to identify them within the bean; instead they have abstract getters and setters to identify them. Using the getters and setters, you can now also include other entity beans. The getters' return types depend upon the relationships type. If a single child-bean instance returns, the instance is the child bean's local interface. In contrast, if multiple child-bean instances return, the instances are a java.util.Collection or a java.util.Set. The bean developer can then describe the relationship, defined within the deployment descriptor's relationship tag, in the EJB's deployment descriptor. Here's an example:

...
<relationships>
  <ejb-relation>
    <ejb-relation-name>User-Demographics</ejb-relation-name>
    <ejb-relationship-role>
      <ejb-relationship-role-name>User-Demographics</ejb-relationship-role-name>
      <multiplicity>One</multiplicity>
      <relationship-role-source>
        <ejb-name>Users</ejb-name>
      </relationship-role-source>
      <cmr-field>
        <cmr-field-name>demographics</cmr-field-name>
      </cmr-field>
    </ejb-relationship-role>
    <ejb-relationship-role>
      <ejb-relationship-role-name>Demographics-belongs-to-Users</ejb-relationship-role-name>
      <multiplicity>One</multiplicity>
      <cascade-delete />
      <relationship-role-source>
        <ejb-name>Demographics</ejb-name>
      </relationship-role-source>
    </ejb-relationship-role>
  </ejb-relation>
</relationships>
...


The example above defines a user bean with a one-to-one, unidirectional relationship to a demographics bean. Let's further examine each XML tag in the deployment descriptor.

The relationships tag tells the container you describe the relationships of the beans contained in this deployment. Each relationship starts with the ejb-relation tag. The ejb-relation-name tag is a human-readable description of the relationship. The ejb-relationship-role tags, of which there are two in each ejb-relation, describe each entity bean's role in this relationship. Each ejb-relationship-role tag contains a human-readable ejb-relationship-role-name tag and describes that bean's role in the relationship. The multiplicity tag describes whether the bean is on the relationship's one or many side. The relationship-role source contains an ejb-name tag, which is the entity bean that participates in the relationship. The ejb-name tag must match one of the EJBs defined in the EJB jar file.

The cmr-field tag is optional. If the described bean lacks a CMR field, it will not be included as demonstrated in the second ejb-relationship-role tag above. However, you must have the cmr-field tag for beans that have a CMR field. The text within the tag contains the cmr-field-name tag describing the CMR field to use in the relationship. Finally, the cascade-delete tag, included in the bean that is the relationship's child, tells the container that if the relationship's parent is deleted, the parent's children should also be deleted.

Relationships overview

The new EJB 2.0 persistence scheme can model eight relationships:

  • One-to-one unidirectional: The parent bean references one child entity-bean instance. A customer with an address serves as a classic example: customers have meaning to us, but addresses without customers mean little.
  • One-to-one bidirectional: Both the parent and child beans reference each other. A classic example of this relationship: a customer and a credit card. Given a customer, you need to find his credit card to charge him for a purchase. The accounting department might also need to look up a customer based upon his credit card information.
  • One-to-many unidirectional: In this relationship, the parent entity bean references many child entity beans, and the child entity beans mean little without the parent. Example: a customer and her associated phone numbers. Knowing a customer, you want to find her telephone numbers; however, you would rarely need to find a customer by knowing a telephone number.
  • One-to-many bidirectional: Each bean in the relationship references every other bean. The parent bean has many child beans, and each child bean references its parent. As an example, think of a customer and his orders. A customer can have many orders, either pending or complete, and a shipping department might wish to find out to which customer a particular order belongs.
  • Many-to-one unidirectional: Many parent entity beans reference a single child entity bean. However, the child entity bean does not refer back to the parents. Airline reservations serve as a classic example. Although a flight may occur multiple times, reservations pertain to a single flight. From the customer's view, you just want to know the given reservation's flight information.
  • Many-to-one bidirectional: Although you can easily model many-to-one bidirectional relationships under the persistence scheme, they are not really unique relationships because they are identical to one-to-many bidirectional relationships.
  • Many-to-many unidirectional: Many parent beans reference many child beans. The child beans either mean nothing without the parent, or you don't need to look up a parent bean based on a child bean. Expanding on the airline reservation example, not all reservations occur with direct flights. A single reservation may include multiple flights; moreover, many reservations may exist for the same flight. Now from our customer's view, you want to know all the flights in the reservation.
  • Many-to-many bidirectional: Many parent beans reference many child beans, which likewise reference many parent beans. An event schedule illustrating the relationship of events and locations serves as an example: many events occur in many locations. Given an event, you may want to find its locations. Given a location, you may also wish to find all the events occurring there.


From the list above, you see three major relationship types: one-to-one, one-to-many, and many-to-many. We will explore each in more detail. First, however, let's explore how the EJB 2.0 specification handles such relationships.

Local interfaces

As previously mentioned, the entity bean models each relationship type using abstract assessors. The return type is either a local interface or a local interface collection. Although local interfaces are not unique to entity beans, their use in constructing relationships does restrict their usefulness. Since relationships use local interfaces that can work only within the same VM, only relationships within a single VM can occur. Therefore, you cannot create relationships with other distributed entity beans. Although that restriction hinders many possibilities, it offers one large advantage: local interfaces are extremely fast. Because a remote call's overhead no longer exists, local interface calls act just like other local method calls to a regular Java class.

One-to-one relationships

Now that you understand EJB relationship basics, let's model your first relationship. For simplicity's sake, start with an easy one-to-one relationship: the customer and address relationship. Because in its simplest sense, the customer address relationship is a one-to-one unidirectional relationship, you model it with one customer bean and one address bean. I keep the entity beans simple to concentrate on defining the relationship.

1 | 2 | 3 | 4 |  Next >
Resources