Recent top five:
Let's talk about exceptions ...
How do you handle exceptions? Do you think upfront about the type of exceptions that you want to catch or do you just let
the outside world handle it?
-- Jeroen van Bergen in JW Blogs
| Enterprise AJAX - Transcend the Hype |
| Memory Analysis in Eclipse |
| Oracle Compatibility Developer's Guide |
| Memory Analysis in Eclipse |
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.
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.
The new EJB 2.0 persistence scheme can model eight relationships:
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.
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.
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.