HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Object-oriented systems analysis and design typically yield an object model whose classes are organized using inheritance and associations. Inheritance represents common interfaces and behavior among different classes of objects. Associations represent statically typed binary relationships between objects that are established and modified during operational use of the system.

When the object model for a system is implemented using an OO programming language, classes and inheritance relationships of the model can be mapped directly into statically defined classes within the language. But associations between objects aren't supported as OO programming language primitives. Thus representation and support for associations can be a crucial issue when implementing object-oriented systems.

This article considers how associations might be represented and supported within the framework offered by Enterprise JavaBeans.

Important Aspects of Associations
Associations Are Determined by Roles

Due to the binary nature of its corresponding relationship, an association is determined by two roles whose names and static types characterize the objects that participate in the relationship. For example, if an association has two roles of type Person, named mother and child, a Person object that plays the mother role is expected to be (in a representational sense) the mother of the related Person objects playing the child role. A UML diagram representing such an association might appear within Rational Rose as shown in Figure 1.

Figure 1
Figure 1:

Cardinality and Navigability Describe Roles
Roles have an associated cardinality. The above model specifies that a child has exactly one mother, but a mother can have any number of children. The other important aspect of a role is navigability. In Figure 1, for purposes of illustration, a directed association link is used to model a system in which a mother knows her children, but the children don't know their mother.

Associations and Inheritance Are Integrated by an Object Model
Associations and inheritance appear in an integrated manner within an object model. Figure 2, derived by elaborating on the initial example in Figure 1, illustrates this by presenting a model in which every Person has exactly one mother and one father, and every Female and Male is a Person and may have any number of associated children.

Figure 2
Figure 2:

Associations Can Be Represented by Methods
When a class of objects is modeled as participating in an association and the related role is navigable, instances of the modeled class are intended to have some way of accessing the objects that play that role. It's therefore reasonable to postulate the existence of a method for computing or accessing an association "role extent" for instances of the class.

As there are four navigable roles in the example above, four different methods would be provided to access role extents. A vector can be used to return n-ary role extents.

public Female Person.mother();
public Male Person.father();
public Vector Female.children();
public Vector Male.children();

In keeping with the use of associations to represent dynamically changing relationships, association modification methods are often appropriate. Depending on the system being implemented, a class that participates in associations may provide "add" and "remove" methods corresponding to its associations' opposing roles. In the current example these methods could appear as follows:

public void Person.addFather(Male f);
public void Person.removeFather(Male m);
public void Person.addMother(Female m);
public void Person.removeMother(Female m);

public void Female.addChild(Person c);
public void Female.removeChild(Person c);

public void Male.addChild(Person c);
public void Male.removeChild(Person c);

An important aspect of association modification is that it generally affects role extents for multiple objects on both ends of an association. For example, adding or removing an association between a mother and child will affect the extent of the child role (accessed from the mother) as well as that of the mother role (accessed from the child). Thus, implementing the dynamics of an association requires more than supporting references between objects.

The approach illustrated above provides a simple and intuitive basis for supporting associations from within an object-oriented programming language: object methods are used to maintain associations and access navigable role extents. But how are these methods to be implemented? The following section offers an approach that might be appropriate for container-managed Enterprise JavaBeans.

EJB Developer vs Deployment Responsibilities
We're concerned here with how to support persistent associations between container-managed entity beans.

Developer Responsibilities

  1. The EJB developer determines an object model and provides EJB classes corresponding to this model. The EJB classes provide various "association methods," as illustrated above, that are used by clients (through remote interfaces) and by other EJBs to maintain associations and access navigable roles.
  2. The EJB developer uses container APIs (from an extension of the EntityContext interface) to implement the association methods.
  3. The EJB developer communicates essential aspects of the object model to the deployment phase within the deployment descriptor to allow the container to support the required associations via its APIs.
Deployment Responsibilities
  1. The EJB deployer inspects the object model provided by the deployment descriptor and implements the required object model associations in a manner appropriate for the specific EJB container technology being employed. For example, when using EJB containers based on object-relational mappings, association tables might be determined and created (in addition to any database tables required for storing object state). For containers based on single-level store object technology, other implementations might be appropriate.
  2. The resulting database schema and other implementation information for the model associations are provided to the container in whatever way is appropriate for the particular container being used. This information is what enables the container to support object-model associations through the association-related APIs in the container's extended EntityContext interface.

An Extended EntityContext Interface with Association Support
An extended container interface provides complete support for computation and modification of role extents. In the simple approach suggested in Listing 1, a vector is used to hold role extents that, after registration, are kept up to date by the container when it executes association modification operations.

Using AssociationSupport
EJBs use the extended container interface to compute and modify role extents. When a role extent is first needed, an EJB class creates an appropriate collection for the extent and then registers it with the container. After this, the container maintains the role extent as required when add- or remove-association methods are called. Listing 2 illustrates how this appears in the case of the Person class.

Comments on the Code
The most important aspect of the approach in Listing 2 is that it relies on the container to compute and maintain role extents. This corresponds with other container responsibilities in the case of container-managed entity beans. In general (assuming bidirectional navigability), two role extents will be updated by the container when an association is modified. Of course, the container will also modify whatever container-dependent state is used to support persistence and the initial registration API. For example, in the case of object-relational mappings, a persistent association table containing foreign keys of associated objects might be updated.

Implicit in Listing 2 is the idea that an EJB is allowed to access other EJBs (not their remote interfaces) directly via registered role extents. Direct access to another EJB within the same container is actually a novel idea in the context of the EJB specification, so the act of registration seems appropriate. For one thing, a container needs to know which objects can and cannot be passivated.

Listing 2 assumes a single global name space for role names and that the class of a target object and a role name uniquely determine an association. A more realistic approach might be to scope role names within association names. Association names for the above example might be chosen as M and F, resulting in the fully scoped role names M.mother, M.child, F.father and F.child.

Other Issues
We haven't discussed the client API for associations. Vector provides a simple collection class that's appropriate for the general-purpose EJB/container API for associations. But the client API for maintaining and accessing specific association roles (provided from the remote interface of the target object) can use types specific to the particular association role involved. For example, when accessing n-ary role extents containing a particular type of object, the collection interface used for finder operations on that type would seem appropriate.

We've avoided discussing container-specific mechanisms made available to deployers in support of associations. However, the overall approach suggested above is consistent with that used by Secant Extreme Enterprise Server for EJB. There, deployment includes creation of association tables and generation of a "metadata" file that describes these tables, the associations they support and the corresponding EJB classes. The metadata file is provided at runtime to a Secant EJB service (container) that loads the corresponding EJB classes and then uses the indicated tables to support persistent associations.

Local/Remote Access
In Listings 1 and 2 the expectation is that associations between EJBs are made visible to remote clients through the beans' remote interfaces. However, "local" associations (available to support business logic but not visible to remote clients) might be useful in some cases.

Conversely, it seems reasonable that an application assembler might want to associate EJBs from separately developed object models. In this case the remote interfaces of the selected EJBs would be provided with association methods, and deployment would provide their implementations (instead of deferring to EJB classes). In this case client applications would be able to make use of associations, but business logic would not.

Thus we suggest "local" and "remote-only" as special kinds of associations in the deployment descriptor. Local associations would be specified by a bean developer and supported by EJB classes. Remote-only associations would be specified by an application assembler and completely supported by remote interface objects. Both possibilities seem potentially useful.

Summary
Inheritance and associations are object modeling ideas that are important when implementing software for complex, real-world systems. The purpose of this article was to condense these general ideas into a simple, concrete form that I hope will be useful for supporting discussion and further work in this area.

Author Bio
Scott Danforth works at Secant Technologies, Inc., in Cleveland, where he focuses on the development and practical application of object-oriented technology. He has a Ph.D. in computer science from the University of North Carolina at Chapel Hill, and is the coauthor of Objects for OS/2 and Putting Metaclasses to Work.
He can be reached at: [email protected]

	

Listing 1: 

public interface AssociationSupport extends 
     javax.ejb.EntityContext 
     { 
       public void registerRoleExtent(Object target, 
                         String roleName, 
                         Vector roleExtent); 
       public void addAssociation(Object target, 
                         String roleName, 
                         Object rolePlayer); 
       public void removeAssociation(Object target, 
                        String roleName, 
                        Object rolePlayer); 
     } 
  
  

Listing 2: 

     public class Person { 
        AssociationSupport ctx; 
  

         public void setEntityContext(EntityContext _ctx) { 
               ctx = (AssociationSupport) _ctx; 
         } 
  

        public Male father() { 
               if (fatherExtent == null) { 
              fatherExtent = new Vector(); 
               ctx.registerRoleExtent(this, "father", 
fatherExtent); 
               } 
               return (Male) fatherExtent.elementAt(0); 
        } 
        Vector fatherExtent = null; 
  

        public void addFather(Male f) { 
               ctx.addAssociation(   this, "father", f); 
        } 
        public void removeFather(Male f) { 
               ctx.removeAssociation(this, "father", f); 
        } 
  

        public Female mother() { 
               if (motherExtent == null) { 
              motherExtent = new Vector(); 
               ctx.registerMotherExtent(this, "mother", 
motherExtent); 
               } 
               return (Female) tmp.elementAt(0); 
      }; 
      Vector motherExtent = null; 
  

      public void addMother(Female m) { 
               ctx.addAssociation(this, "mother", m); 
      }; 
      public void removeMother(Female m) { 
               ctx.removeAssociation(this, "mother", m); 
      } 
   } 
  

   ... similarly for Male and Female 


  
  
      
 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.