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’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
-
Aggregate Details Patterns (15 messages)
- Posted by: Jeff anderson
- Posted on: July 16 2000 16:14 EDT
Threaded Messages (15)
- Aggregate Details Patterns by Floyd Marinescu on July 16 2000 21:51 EDT
- Aggregate Details Patterns by Jeff anderson on July 17 2000 17:53 EDT
-
Aggregate Details Patterns by Brian Matalus on July 20 2000 05:10 EDT
- Aggregate Details Patterns by Jeff anderson on July 21 2000 12:33 EDT
-
Aggregate Details Patterns by Brian Matalus on July 20 2000 05:10 EDT
- Aggregate Details Patterns by Jeff anderson on July 17 2000 17:53 EDT
- Aggregate Details Patterns by Kenneth Delong on July 25 2000 12:13 EDT
- Aggregate Details Patterns by Peter Delahunty on July 30 2000 17:50 EDT
- Aggregate Details Patterns by Jeff anderson on July 31 2000 18:15 EDT
-
Aggregate Details Patterns by pankaj grover on August 02 2000 07:04 EDT
- Aggregate Details Patterns by Jeff anderson on August 04 2000 03:37 EDT
-
Aggregate Details Patterns by pankaj grover on August 02 2000 07:04 EDT
- Aggregate Details Patterns by Jeff anderson on July 31 2000 18:15 EDT
- Aggregate Details Patterns by Robert McIntosh on August 08 2000 10:01 EDT
- Aggregate Details Patterns by George Gardiner on September 28 2000 20:51 EDT
- Aggregate Details Patterns by jeff anderson on November 04 2000 01:24 EST
-
Aggregate Details Patterns by Bill Smith on November 06 2000 10:57 EST
-
Aggregate Details Patterns by jeff anderson on November 14 2000 10:43 EST
- Aggregate Details Patterns by ashish joshi on December 12 2000 06:07 EST
-
Aggregate Details Patterns by jeff anderson on November 14 2000 10:43 EST
-
Aggregate Details Patterns by Bill Smith on November 06 2000 10:57 EST
- Aggregate Details Patterns by jeff anderson on November 04 2000 01:24 EST
-
Aggregate Details Patterns[ Go to top ]
- Posted by: Floyd Marinescu
- Posted on: July 16 2000 21:51 EDT
- in response to Jeff anderson
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;
} -
Aggregate Details Patterns[ Go to top ]
- Posted by: Jeff anderson
- Posted on: July 17 2000 17:53 EDT
- in response to Floyd Marinescu
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: Brian Matalus
- Posted on: July 20 2000 17:10 EDT
- in response to Jeff anderson
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: Jeff anderson
- Posted on: July 21 2000 00:33 EDT
- in response to Brian Matalus
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: Kenneth Delong
- Posted on: July 25 2000 12:13 EDT
- in response to Jeff anderson
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. -
Aggregate Details Patterns[ Go to top ]
- Posted by: Peter Delahunty
- Posted on: July 30 2000 17:50 EDT
- in response to Jeff anderson
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. -
Aggregate Details Patterns[ Go to top ]
- Posted by: Jeff anderson
- Posted on: July 31 2000 18:15 EDT
- in response to Peter Delahunty
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: pankaj grover
- Posted on: August 02 2000 19:04 EDT
- in response to Jeff anderson
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: Jeff anderson
- Posted on: August 04 2000 15:37 EDT
- in response to pankaj grover
Exactly.
Jeff -
Aggregate Details Patterns[ Go to top ]
- Posted by: Robert McIntosh
- Posted on: August 08 2000 10:01 EDT
- in response to Jeff anderson
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
-
Aggregate Details Patterns[ Go to top ]
- Posted by: George Gardiner
- Posted on: September 28 2000 20:51 EDT
- in response to Jeff anderson
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
-
Aggregate Details Patterns[ Go to top ]
- Posted by: jeff anderson
- Posted on: November 04 2000 01:24 EST
- in response to George Gardiner
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
-
Aggregate Details Patterns[ Go to top ]
- Posted by: Bill Smith
- Posted on: November 06 2000 10:57 EST
- in response to jeff anderson
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: jeff anderson
- Posted on: November 14 2000 22:43 EST
- in response to Bill Smith
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 -
Aggregate Details Patterns[ Go to top ]
- Posted by: ashish joshi
- Posted on: December 12 2000 06:07 EST
- in response to jeff anderson
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