Avijeet Dash and Satyabrata
Dash
The appropriate design of entity beans has been a subject of on-going debate.
Entity beans represent shared, transactional persistent objects. The
best-practice while designing entity beans is to avoid as much as inter-entity
bean communications, as they are resource-intensive and affect the performance
of the system. To avoid inter-entity bean communication the entity beans has to
be designed to represent a graph of objects rather than one fine-grained object.
One of the bad-practice is to map each table in the database to an entity bean.
This is a multi-dimensional problem. The symptoms of the problem are the system
becomes slow and difficult to maintain.
Entity beans are remote objects and when entity beans are designed in a
schema-isomorphic manner i.e. individual beans represent one table each in the
database, the fine-grained entity beans. The attributes map in a one-to-one
manner to the tables and the methods are fine-grained set and get methods. The
problem happens when fine-grained entity beans represent dependent objects,
whose life cycle is managed by some other object. When dependent objects are
implemented as entity beans that leads to inter-entity bean communications,
which are expensive, and resource crunching. Typically entity beans are
considered as one row in a table and that leads to the design of fine-grained
entity beans. Composite entity changes this view and one entity bean represents
a collection of data across multiple tables instead of one row in one table.
The best practice is to design coarse-grained persistent business objects as
entity beans. In such cases the entity bean represents a graph of objects. The
graph of objects is between a coarse-grained parent object and dependent child
objects. The relationship can be represented in form of a tree with the parent
(coarse-grain) object as the root and the dependent objects as leafs which in
turn may have more dependent objects. An object is coarse-grained when it
manages the life cycle of itself as well as that of the dependent objects, which
doesn’t have any existence of their own leaving the coarse-grained object.
For example
Objects like Asset and Contract are dependent objects on Account
object. Account object should be designed as a coarse-grained entity bean. We
avoid creating entity beans for the dependent objects.
Objects like Address, Name and Phone numbers are dependent objects on Person.
Person is the parent object, which manages the life cycle of such objects. If
Person doesn’t have an independent existence without an account then it
becomes a dependent object to account.
Dependent versus Independent Objects
Coarse grained objects like Account and Person can be implemented as java
objects contained in AccountEntity, PersonEntity objects or AccountEntity,
PersonEntity objects themselves may implement as the coarse grained objects.
Sequence diagram for
Composite entity or Aggregate Enity
Implementing the Composite Entity Pattern
When a Composite entity implements the Coarse grained object, It holds its
own fields as well as the dependent objects. Clients expect coarse-grained
methods as well as composite view of the data. Composite entity exposes a
composite view of the data comprising of its own data and data from dependent
objects.
When multiple levels of dependent objects are present, loading and storing of
data of multiple dependent objects can cause considerable overhead. To optimize
loading and storing of data through ejbLoad() and ejbStore(), lazy loading
strategy and Dirty marker strategy has to be implemented. The EJB2.0
Specification addresses the Lazy loading strategy and the Store optimization
strategy.
The Lazy Loading strategy is about not loading dependent objects unless they
are required. It’s about Loading dependent objects data on demand for first
time and reloading them on subsequent ejbLoads. Store optimization is about
using a dirty marker to identify objects that have been updated and store only
those to the persistent store.
Composite Entity beans can be implemented as BMP (bean managed persistence)
as well as CMP (container managed persistence) beans. To implement as CMP beans
an O-R mapping tool has to be used. Generally it’s implemented as BMP. One
good practice could be to implement fine-grained entity beans as CMP bean and
coarse-grained bean using BMP. To avoid inter-entity direct interaction one
other approach could be using entity beans in session façade methods.
Sample Code
/*
This sample code is found at http://www.phptr.com/corej2eepatterns/codeChap8_2.html#ex8.18
*/
Reference:
http://www.objectarchitects.de/ObjectArchitects/orpatterns/index.htm?EJBPersistence/index.htm
http://www.theserverside.com/patterns/thread.jsp?thread_id=240
http://www.sdmagazine.com/documents/s=745/sdm0004c/0004c.htm
http://developer.java.sun.com/developer/restricted/patterns/AggregateEntity.html
http://www.jpeople.com/wbug/downloads/J2EE_Patterns-WBUGOct2001.pdf
http://www.refactoring.com/catalog/eliminateInterEntityCommunication.html
http://www.devx.com/premier/mgznarch/Javapro/2001/01dec01/kk0112/kk0112-1.asp
http://theserverside.com/discussion/thread.jsp?thread_id=706
Core J2EE Patterns, Deepak Alur, John Crupi, Dan Malks http://developer.java.sun.com/developer/technicalArticles/J2EE/patterns/
(The authors are senior developers at MindTree Consulting. They can be
reached at avijeetd@mindtree.com
and satyabrata_dash@mindtree.com.
)