Aggregate Details Patterns

Discussions

J2EE patterns: Aggregate Details Patterns

  1. Aggregate Details Patterns (15 messages)

    The Aggregate Detail object


      This pattern combines the concept of using serializable detail objects to set and get the values of Entity Beans (see the detail object pattern already listed) with the idea (mentioned in "Mastering Enterprise Java Beans" by Ed Roman)of having Entity Beans contain references to other child Entity Beans in order to represent a complete object graph.

      The Detail object Pattern states that the Detail class should contain all the fine grain getters and setters used to modify an Entity Bean's internal state . It also states that all Entity Beans should inherit from the same Detail class that they both return and pass in their 'getDetail' and 'setDetails' method.

      The Aggregate Detail Pattern would take this notion one step further by having the Detail class represent the object graph instead of the Entity Bean. This would enable a client to modify and retrieve an Entity Bean's complete object graph in one network trip using a 'getAllDetails' and setAllDetails' method.

      The AggregateDetails class will contain some sort of array or collection that would hold references to other subordinate or 'child' Detail classes in order to represent an object graph. Our entity bean class will also have a reference to this collection by default of it extending from the detail object . The Entity Bean will use this collection to store a 'child' entity objects when the container calls it's 'ejbLoad' method.

      The main difference in this pattern to the regualar Detail Object pattern would be the method 'getAllDetail()' and 'setAllDetails()' in the Entity Bean class. The 'getAllDetail()' method would be responsible for instantiating an aggregate detail object, traversing the object structure of the Entity Bean, assigning it's contents to the aggregate detail object, and finally returning this object to the client. An Example Aggregate Detail class with it's matching Entity Bean class is shown below.


    This is the Aggregate Detail class it is exactly like a regular detail class but it contains a vector to contain an open number of child objects as well as an array to hold an open number of child primary key’s.

      public class ParentModel implements,Serializable{
        protected String msProperty1;
        protected String msProperty2;
        ...

        protected int[5] miChildKey; //we will assume a maximum of 5 children just for this example could be limitless

       //this will store all the child objects of this object
       protected Vector mChildEntities=new Vector();

      public String getProprty1(){
        return msproperty;
      }
      public void setProperty1(String psProperty1){
        msProperty1=psProperty1;
      }
      ...
    }

    This is the Entity Bean class. It will store refrences to 'child' entity beans when loaded. The 'getCompleteDetails' will return an object that represents the bean's complete graph (it will contain 'child' detail objects.

    public Class ParentEB extends ParentModel implements javax.ejb.EntityBean{

      ...
      public void ejbLoad() throws javax.ejb.EJBException ,
      java.rmi.RemoteException{
      //locate, load, and store a reference to all 'children'
        entity Beans of this Parent
      for(int i=0;i<5;i++){
        if (miChildKey[i]!=null){
          // locate child entity depending
          // on value of miChildKey[i] and store it to
          // mChildEntities(i)
          mChildEntities(i)!=createChildHome().findByPrimaryKey
          (new ChildPK(miChildKey[i]);
         }
        }
      }

      //this will return the complete object graph in the form
      of an Agregate Detail object
      ParentModel getAllDetails(){
        DetailOb pParentDetails=new ParentDetailOb ();
        pParentDetails.setProperty1(getProperty1())
        pParentDetails.setProperty2(getProperty2())
        ...
    //call the getAllDetail method on the Child entity references of this Entity object and save them to the Child Detail objects of the Detail object we are going to return
        for(Iterator i= mChildEntities.iterator();
        i.hasNext );i.next()){
          int piChildIndex=0;
          pParentDetails.setChildDetails( piChildIndex++ ,
          ((ChildEntity)I).getAlldetails() );
        }
        return pParentDetails;
      }

      For example if you called 'getAllDetails()' on ParentEB that had a reference to a ChildEB it would return a ParentModel object than contained a ChildModel object. The Setter would do the opposite, basically passing the ParentModel to the 'setAllDetails()' method of the ParentEB.This would set the ParentEB&#8217;s data (just like in the detail object pattern) as well as as set the ChildEb data from the ChildModel object contained in the ParentModel.

      This would assume you are not using lazy instantiation because you have a requirment for the complete graph of the object when using the getAllDetails method. If you did not want to always return or set the complete graph of the object you also could have a regular 'getDetails' and 'setdetails' method that would return the same object but with null references to the 'child' detail objects.

      One weakness of this pattern is that every Entity Bean that uses a 'getAllDetails' and 'setAllDetails' would contain close to identical code to set and get the respective child objects. One solution would be to have an 'AggregateDetail' base class that contain the mChildEntities vector as well as a 'getChildDetails' and 'setChildDetails'. The Detail object could extend from this class. You could then use the 'Composite' pattern to delegate calls throughout the object structure.

      Any thought,comment, or suggestions on this pattern would be greatly appreciated.

    Jeff


    Threaded Messages (15)

  2. Aggregate Details Patterns[ Go to top ]

    Thanks for the great pattern Jeff!

       I have two comments/suggestions:

    1) Your pattern seems to apply only to parent/child one to many relationships. What about one to to one? For example, a Car Entity Bean may have a one to one relationship with a Manufacturer entity bean, shouldn't that be included in the object graph?

    2) I think that returning a graph of details objects is useful, but a client should have some control over how many "levels deep" the returned object graph goes. I can think of many situations where a client wants information about a particular entity bean and just its immediate relationships, not potentially thousands of entity beans that are "indirectly" related.

       My proposed solution is to amend getAllDetails() as follows:

    getAllDetails(int levels);

       Now the client can control how deep an oject graph it will get. On the bean side, the getAllDetails(int levels) method will now look like:

    //this will return the complete object graph in the form of an Agregate Detail object
    ParentModel getAllDetails(int LEVELS){
       DetailOb pParentDetails=new ParentDetailOb ();
       pParentDetails.setProperty1(getProperty1())
       pParentDetails.setProperty2(getProperty2())
                               ...
       if (LEVELS==0)
          return pParentDetails;

       for(Iterator i= mChildEntities.iterator(); i.hasNext );i.next()){
          int piChildIndex=0;
          pParentDetails.setChildDetails( piChildIndex++ , ((ChildEntity)I).getAlldetails( LEVELS-- ) );
       }
       return pParentDetails;
    }
  3. Aggregate Details Patterns[ Go to top ]

    Thanks for the comments Floyd!
    Actually I was thinking that a one to one relationship would have be almost identical to my original pattern but the Parent Detail class would store a reference to a child entity bean in either a vector of one or in a direct reference to A Child detail class. If the latter is chosen then since the Child entity class extends from the Child detail model we could store a reference to a Child entity bean in the Parent Entity class when the Parent is loaded. Of course when using this Child entity object we would have to cast it to and from the Child Entity Bean type as it is being stored in a Child Detail Class reference.
    The Levels idea is a pretty good one! I can think of plenty of examples that would need this type of functionality.
    Jeff
  4. Aggregate Details Patterns[ Go to top ]

    Actually, I think what you are describing here is really something more like a ComplexValueObject.

    SimpleValueObject - get/set methods for accessing data. No nested ValueObjects.

    ComplexValueObject - get/set methods for accessing data. get methods for accessing nested ValueObjects.

    You would definately want to use projections and lazy loading. Projections allow you to specify which data fields you want returned, and lazy loading insures that objects are only realized when/if they get used.

    This patterns has worked very well. If you add a two methods... from/toXML()... you've got a peach.

    Thoughts?

    bmatalus@fusionally.com
  5. Aggregate Details Patterns[ Go to top ]

    COuld you explain the from/toXML()... in a little more detail Brian? I am unsure of it's purpose but would love to hear more.
    The lazy loading is a good idea, instead of finding child beans when we load a parent we could only find them when a getAllDetail() or setAllDetails() method is being called.
    Jeff
  6. Aggregate Details Patterns[ Go to top ]

    I wonder how this strategy compares with Coarse-Grained Entity Bean. That pattern says separate objects should NOT be modeled as independent entity beans if they don't have an independent life-cycle. In other words, an OrderLineItem shouldn't be it's own bean, it should be a helper/dependent object, and part of the Order entity bean.

    This is even promoted in the EJB spec, v1.1, section 9.1.2.

    I realize this leads to nasty BMP code, but hopefully the tools will catch up soon.
  7. Aggregate Details Patterns[ Go to top ]

    You seem to talk about having Child entity bean. Which by child i assume means the entity bean is dependant on another entity bean (it's parent). The ejb spec specifically recommends avoiding this type of design (fine grain against cause grain eb's) It says to use ordinary classes for child entities. Entity beans are supposed to be only top level independant entites in a system. So my point is if you are using normal classes as child entities as the spec recommends then you already have detail objects created. These can then be inside the detail object of the top level entity bean.
  8. Aggregate Details Patterns[ Go to top ]

        There are only certain circumstance where I would recommend this pattern, it is not ideal in all situations. If your parent has dependant data that is completely dependant then by all means use the coarse grain pattern. However if for example you have generic bycicle parts (children) that can be used by several different types of bicycles (parent) than it is my opinion that the Aggregate Details Patterns would be a better choice, that way the dependant (child) entity beans can be pooled independantly of the parent.
    Jeff
  9. Aggregate Details Patterns[ Go to top ]

    Are u trying to say that in case of composition scenarios like parent and wing relationship course gained pattern would be preferable whereas in case of aggregation scenario details object pattern would be more suitable.

    Pankaj
  10. Aggregate Details Patterns[ Go to top ]

    Exactly.
    Jeff
  11. Aggregate Details Patterns[ Go to top ]

    I really like this pattern and use it in two current projects that I work on. I got the original idea from Sun's Design Guidelines (section 5.5.2). While at the moment we are not using EJBs, when we do move to EJBs in the next couple of months, our current objects that we have defined will be our detail, value, etc. objects. We also use business interface for our domain definitions, so that when we do move to EJBs, it will be relatively painless to the rest of the app. A good article on this is at:http://www.devx.com/upload/free/features/javapro/1999/10mid99/jg1399/jg1399.asp

    In our application the idea of selective levels can't be used, but I really like the idea. If you really wanted to get fancy, you could implement the equivalant of a "where" clause for returning children. Might get complicated, but could be useful.

    We also use something very similiar to the toXML/fromXML. I have a utitility class that converts the whole graph to an XML document. We use this format as our serialization from the client (an applet) to the server over HTTPS. Also by doing this we open up the posibility for app-app communication in the future.

    Keep the good work,
    Robert
  12. Aggregate Details Patterns[ Go to top ]

    Could you please clarify how your pattern accomodates insert, update, delete on children in a one to many relationship via get() and set() accessors. From your example I can see how it easily accomodates adding new child members and retrieves them, but how do you accodate updating existing children or deleting them?

    George
  13. Aggregate Details Patterns[ Go to top ]

    updates are handled by passing an aggregate detail object to the aggregate ejb with a setdetails(detailBean) method. The method would first update the current fields of the ejb from the detail bean, then call setdetails on the child bean of the ejb, passing in the child detail bean as a paramter.

    public void setDetails(detailBean d){
      this.name=d.name;
      this.age=age;
      ...
      this.childEJB.setDetails(d.getChildDetails());
    }
    Rob thanks for the encouragement
  14. Aggregate Details Patterns[ Go to top ]

    One thing that seems to be a shortcoming of entity beans is that the spec fails to address the need for optimistic locking. It appears to me that the details pattern (and aggregate details pattern) would depend on optimistic locking quite heavily. While this isn't that hard to do for simple relationships, how would you propose doing that for 1-M relationships?

    Also, do you have any samples for handling the insert, update, delete functionality for 1-Ms?

    TIA,
    Bill
  15. Aggregate Details Patterns[ Go to top ]

    Bill
    Optimisitic locking can be handled by having an extra "time stamp" field. when passing a detail bean into an aggregate bean, first check the time stamp of the detail object to the time stamp of the entity bean, if the detail object is older than someone else has written to the table. throw an exception that will nest itself all the way back to the bean that originally called the exception this will cause any writes in a transaction to abort.
    Jeff
  16. Aggregate Details Patterns[ Go to top ]

    Jeff,

    Do you have any code example for this pattern. e.g. Order entity bean containing order line items. I want to know how to manage updates/deletes/inserts for dependent object.
    Thanks
    ashish