A Pattern Language for Java 2 Enterprise Edition Applications
Jay Walters, Chief Scientist, netNumina Inc. - jwalters@computer.org

This article will present an outline of a subset of a pattern language for Java 2 Enterprise Edition (J2EE) development. I call it an outline of a pattern language because only condensed patterns will be included due to space considerations. For this article, a condensed pattern will consist of a Name, a Context/Motivation, a Description and a list of Related Patterns. As you will see, these condensed patterns are much shorter than normal patterns. It is only a subset, because this article will present just five condensed patterns from a larger pattern language.

While the information in this article is just a beginning, developers can use it to improve their ability to develop robust and scalable J2EE applications. These condensed patterns apply to both the interfaces and internals of the EJB portion of the J2EE environment. This article will focus on the condensed patterns and the synergy between them. It will be shown that applying them in combination can provide benefits above and beyond applying them individually.

The pattern language from which this article is excerpted was developed at netNumina while building a framework for generating J2EE applications from high-level UML Class Models. The codename of the framework is Akutan1, an active volcano in the Aleutian Islands. We liked the creational nature of a volcano as an icon for the program generator.

Akutan relies on the fact that most UML modeling tools can export the models in XML documents, according to the XMI standard. The framework processes the XML document with a number of XSL stylesheets to generate all the artifacts required for an end-to-end J2EE application.

The target environment for our framework includes at least three EJB 1.1 compliant application servers and multiple RDBMS products. We use Bean Managed Persistence (BMP) entity beans to provide our persistence layer. We use BMP because we wanted a common persistence model across all supported application servers and we could not meet that goal using Container Managed Persistence (CMP). We use JSPs and Servlets with the Apache Struts framework for our presentation layer.

When we began development of the framework we identified a set of patterns from our experience, which we felt, would lead to robust applications. As we implemented the framework we added more patterns to our list, derived some new patterns and began to see synergies between the various patterns. At that point we realized that we had assembled a pattern language for developing robust J2EE applications.

I will present the five condensed patterns in a specific order as they build upon each other. Diagram 1 shows the relationships between the various condensed patterns, the arrows between the various blocks indicate the dependency relationships.

Diagram 1 - Design Pattern Relationships

The rest of the article will take the form of applying the various condensed patterns to a simple application.  This application will start with a very basic design.  As each condensed pattern is applied we will see how it improves the design.  The application will contain a single business object, an order with associated line items.  Diagram 2 shows a simplified UML Class Model for the application.

Diagram 2 - Example Application Class Model

Diagram 3 shows a potential interaction between a JSP client which will display an order and its' line items and the entity beans which model the Order business object.  I've taken the liberty of simplifying the diagram by leaving out any cache management, which the EJB container might be doing.  As shown the EJB Container will delay activation of the Entity Bean until the client actually attempts to access it.

Diagram 3 - Sequence Diagram for Naïve Implementation

Diagram 3 indicates potential performance problems with the basic implementation.  To respond to one client request for an order, the application makes eight remote method calls and five database queries.

The first condensed pattern, Value Holder, is structural in purpose. The use of Value Holder will reduce the number of remote method calls and reduce coupling between the presentation and persistence layers.

Value Holder

Context/Motivation

The client is calling many fine grain remote methods on an object in order to retrieve different attributes.  There is no intrinsic reason to call multiple methods to retrieve the information.   Remote method calls are much more expensive than calls to local methods.  To improve performance we want to reduce the number of remote method calls.

Description

The Value Holder condensed pattern addresses the problem of redundant remote calls when a client is trying to retrieve many attributes from the same remote object.  The name Value Holder was chosen to indicate it is an object with no interesting behavior, very similar to the Value Holder concept in CORBA.  A Value Holder contains a group of attributes from another object, which are commonly used together.  The interface of the object is changed to support a new method, which returns a Value Holder containing a complete or partial copy of the current state of the object. There can be more than one Value Holder associated with an object and/or multiple methods of retrieving Value Holders from the object.

Related Patterns

Replicate2, Data Transfer Object3

When using a Value Holder, the client needs to call only a single remote method to retrieve all needed data from an entity bean.  This reduction in network traffic can provide a significant boost to application performance.  A side effect of introducing this new object between the persistence layer and the presentation layer is to reduce coupling and thus make the application more maintainable.

This condensed pattern can also be applied to updates of the entity.  The client can update the entire state of the entity with a single remote call.  The update by Value Holder method can also include validation logic which checks across attributes to ensure the state of the bean will be consistent and valid after the update is applied.

The use of Value Holders is not really pure object oriented design.  It does illustrate one of the challenges of designing a distributed object system, trading off purity of object-oriented design versus a design with acceptable performance.

As a result of implementing the Value Holder condensed pattern, we will add two new classes to the application, OrderVH and LineItemVH.  The source code for OrderVH is shown below, LineItemVH does the same for the LineItem entity bean.

public class OrderVH implements java.io.Serializable
{
  private int orderId;
  private Date orderDate;
   private Date shipDate;

  public OrderVH(int orderId,
Date orderDate,
Date shipDate) {
    this.orderId = orderId;
    this.orderDate = orderDate;
    this.shipDate = shipDate;
  }

  public int getOrderId() {
return orderId;
}

  public Date getOrderDate() {
return orderDate;
}

  public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}

  public Date getShipDate() {
return shipDate;
}

  public void setShipDate(Date shipDate) {
this.shipDate = shipDate;
}
}

Two new methods need to be added to the remote interface and implementation of each of the entity beans, the new methods in the Order remote interface are shown below.  Similar changes should be made to the LineItem remote interface and to the implementation of each entity bean.

public interface Order extends javax.ejb.EJBObject {

  ...

  public OrderVH getOrderVH();
  public void setOrder(OrderVH order);
}

 

By applying the Value Holder condensed pattern to the basic design we have cut the number of remote method calls from six to three.  In a real application with many attributes per entity this will provide a significant performance boost.

The next condensed pattern, Dependent Objects, is also structural in purpose. The proper application of Dependent Objects will reduce the amount of database interaction required to load the Order business object.

Dependent Objects

Context/Motivation

A simple mapping of each row in the database to an entity bean results in complex business objects spanning multiple entity beans, and not being encapsulated.  Remote clients may have access to the internals of the business object because of this lack of encapsulation. Interaction between the various entities will be inefficient in terms of both method calls and database operations.  Method calls between entity beans are considerably more expensive than calls between plain JavaBeans.  Even though EJB Containers can cache entity beans, and the persistence manager can cache raw data, activating a set of entity beans one by one can easily be more expensive than creating a set of simple JavaBeans all at once.

Description

The Dependent Objects condensed pattern addresses the problem of encapsulating business objects by modeling business objects as a single entity bean and making the dependent objects within JavaBeans.  Because JavaBeans have no remote interface, all access to the dependent objects will be via the entity bean.  This allows the entity bean to manage the life cycle of the dependent objects.  With this control, the entity bean can optimize the dependent object load and store operations.  Finally, interactions between the entity bean and the dependent objects are all local method calls, which improves the efficiency of the application.

Related Patterns

Dependent Objects4, Coarse Grain BMP Beans with Dependent Value Objects5

When the EJB 2.0 specification is complete and EJB 2.0 compliant containers become widely available, Container Managed Persistence (CMP) will provide better support for implementing this model.  This should lead to improved performance and resource usage from CMP entity beans, and allow more developers to use CMP.

After applying the Dependent Objects condensed pattern the application will implement Order as an entity bean and the LineItems as dependent objects.  This design is consistent with observed behavior where we never expect line items to exist without their order.  No changes are required to the database schema in order to use this model, there is still a simple mapping between database rows and objects.

All access to the LineItem dependent objects will be via the Order entity bean. The interface will be written in terms of LineItemVH objects. The source code for a new value holder, OrderDeepVH is shown below.  It extends the shallow OrderVH class to include the LineItem dependent objects associated with the Order.

public class OrderDeepVH extends OrderVH
implements java.io.Serializable {
  private Collection items;

   public OrderDeepVH(int orderId,
Date orderDate,
Date shipDate,
                    Collection items) {
     super(orderId, orderDate, shipDate);
    this.items = items;
   }

  public Collection getItems() {
return items;
}

  public void setItems(Collection items) {
this.items = items;
}
}

The code shown below includes two new methods, the first to get a new value holder and the second to update the Order by value holder. For simplicity I will force all updates to the dependent objects to go through the update method. When applying this condensed pattern to a real application you might want to add methods to add or remove dependent objects by their value holder.

public interface Order extends javax.ejb.EJBObject {
  ...

   public OrderDeepVH getOrderDeepVH();
   public void update(OrderDeepVH order);
}

The Order entity bean will include methods, which allow access to the LineItems, and the Entity Bean will need to track whether they have changed and must be written to the database.  During the Order entity bean's ejbLoad method it will load all the associated LineItem objects from the database.   The relationship between Order and LineItem is an ordered 1:n relationship. This naturally maps onto an implementation of the List interface. The list should be smart enough to do some bookkeeping and determine if a LineItem has changed or not before updating the database. This brings me to the next condensed pattern Lazy Load.

Lazy Load

Context/Motivation

Within an application, objects typically exist within a network of related objects.  There might be times when you need access to the transitive closure of this network, and other times when you do not.  It can be expensive in terms of processing and memory to load these objects into memory, especially if they are not all needed.

Description

The Lazy Load condensed pattern is primarily applicable when related objects are not always referenced.  With Lazy Load an object is not fetched from the database until it is actually needed. An additional benefit of this condensed pattern is that the specific client requesting the lazily loaded object will be the one who incurs the entire cost of loading the object from the database.

Lazy Load is typically implemented through the use of a Proxy, which transparently performs the evaluation the first time the object is accessed.

Related Patterns

Lazy Evaluation8

Lazy Load is often implemented using a proxy for the item to be loaded.  When a request is made to access the items, the proxy will load the items from the database.  We can leverage this proxy to also do the bookkeeping about which LineItems have been inserted, deleted or modified.  We can then make use of this information from within the ejbStore method of the Order entity bean. The lazy load feature will be used if a client calls getOrderVH() on a bean, which needs to be loaded from the database. In this case the dependent objects will not be loaded into memory unless a later client call requires them.

My implementation of a Lazy Load proxy was inspired by Dan O'Connor, you can find links to his article and source code at his website (http://www.mvcsoft.com).  The proxy handles both lazy loading and bookkeeping of changes to the dependent objects.  Diagram 4 shows the important details of this model.  The SmartList abstract class implements the List interface and adds the appropriate bookkeeping to each of the methods.  It uses the LineItemList classes' load and store methods to interact with the database. The LineItemList load method essentially contains the code supporting dependent objects from the Order entity bean's ejbLoad method.  The LineItemList store method is more involved since it now has the data to identify, which LineItems have been inserted, updated or deleted.

Diagram 4 - Class Model for Lazy Loading Dependent Object Proxy

Diagram 5 - Sequence Diagram for Improved Implementation

At this point the worst performance issues have been mitigated via the application of the Value Holder, Dependent Objects and Lazy Load condensed patterns.  Another important issue in any enterprise application is coupling between components and its' impact on the maintainability of the system.  The next condensed pattern, Session Facade, is structural in purpose. Session Facade addresses reduced coupling between the persistence and presentation layers.

Session Facade

Context/Motivation

Embedding detailed knowledge of the internals of the server application into client application results in too close a coupling between the two layers.  This close coupling makes it extremely difficult to make changes to the server portion of the application without corresponding changes to the client.

Description

The Session Bean Facade condensed pattern is a specialization of the GOF Facade pattern, which implements the facade as a session bean.  Usually it will be a stateless session bean, though if there is state to maintain a stateful session bean could be used.  The facade provides a high level interface for the component.  This hides the details of the persistence layer (entity beans or other mechanism) and server logic from the client.

Related Patterns

Session Entity Facade6, Facade at the Distribution Boundary2, Facade7

The primary purpose of the Session Facade condensed pattern is to hide the details of one component from another, a side effect is that it is easier for other developers to understand the interface to the component because the implementation will be simpler to understand than the underlying details.  To this end, each facade should be kept as simple and uncluttered as possible.  It should contain only a single set of closely related operations. In a real application these operations implement the business logic.  When using this condensed pattern you will also need to use Value Holders to pass data between through the facade.

When we hide the details of the component from the client, it becomes easier to make changes to the implementation without impacting the client.  For example, certain methods in the facade could be changed to go directly to the database instead of to entity beans.  Further, if desired, the entity beans could be completed replaced with another implementation of the persistence layer.

I have described several condensed patterns and applied them to the sample application improving its' efficiency in terms of remote method calls and database interactions, and reducing the amount of coupling between the client programs and the EJBs.  Next I will present a condensed pattern, Optimistic Locking, which addresses the issue of concurrency control. I will make a differentiation between two types of transactions. Database transactions are short and execute in the context of a single client request.  Business transactions may be long lived, involve user interaction, and may span one or more database transactions.  I will not address database transactions, as there are many good resources, which provide information on concurrency issues within the database.

Optimistic Locking

Context/Motivation

A common situation within an application is for a user to request to view one or more objects, and then sometime later submit changes to those same objects.  During these business transactions it is not always practical to lock the objects included in the transaction and exclude others from viewing or changing them.  However, an application needs some protocol in order to keep users from overwriting each other's changes to shared data.

Description

In the Optimistic Locking condensed pattern, when a change is about to be made to an object at the server, the state of the object is checked against some original state, which was current when the user initially read the object.  If the state matches, then the update is allowed.  If the state does not match, then the change is not allowed because the update is based on stale data.

Optimistic locking works well if access patterns are well distributed over a large dataset making the probability of collisions low and the cost of recovery from a collision is low.  Optimistic locking is not well suited for an environment with many collisions or expensive recovery from a collision. 

Related Patterns

Optimistic Locking6

Optimistic Locking can be implemented in several ways, but the basic idea is that some attribute or attributes will be checked when the entity is updated to ensure that no other transaction has updated the object since it was read for the current business transaction.  This can be accomplished using a version number, a timestamp or by checking all the attributes in the entity against the values originally read from the database.  When using a timestamp or version number this additional information needs to be stored as an attribute in the entity.  While checking the original values of all attributes doesn't require changes to the persistence schema, it does require the entire original state be saved and of course it may or may not include any dependent objects.

I prefer a version number because there is no issue of clock synchronization across machines and no need to retain a copy of the original state.  In order to modify the example application to use Optimistic Locking, an integer version number attribute will be added to each of the objects, Order and LineItem.  The simplest way to track this state throughout a business transaction is to encapsulate the version number in the Value Holder where it can be maintained as a private read-only attribute. In our framework, we save this session state in the user's HttpSession object in the Servlet container.

The new class, ValueHolder, that is the base class for all value holders manages the version attribute.

public class ValueHolder {
  private int version;

  public ValueHolder(int version) {
       this.version = version;
  }

  public int getVersion() {
return version;
}
}

 

The required modifications to the OrderVH class are shown below, similar changes must be made to the OrderDeepVH and LineItemVH classes as well.

public class OrderVH extends ValueHolder 
implements java.io.Serializable {
   private int orderId;
   private Date orderDate;
   private Date shipDate;

   public OrderVH(int version,
int orderId,
Date orderDate,
Date shipDate ) {
    super( version );
    this.orderId = orderId;
    this.orderDate = orderDate;
    this.shipDate = shipDate;
   }

   ...
}

In summary, I have presented five condensed patterns for J2EE applications and a brief overview of how we implemented them in our J2EE framework.  Their use can improve performance, reduce coupling between the presentation and persistence layers, and provide a simple but effective locking strategy. While each of these condensed patterns might not be right for every application, most J2EE applications will benefit from their use.

References

1  netNumina's Akutan Framework, http://www.netnumina.com/vision/technology/framework.html.

2  A Small Pattern Language for Distributed Component Design, Kyle Brown et al, http://members.aol.com/kgb1001001/Articles/PLoP99/brownfinal.pdf.

3  Data Transfer Object, Portland Pattern Repository, http://c2.com/cgi-bin/wiki?DataTransferObject.

4  EJB Version 2.0, Proposed Final Draft 2, April 21, 2001, http://java.sun.com/products/ejb/2.0.html.

5  Coarse Grained BMP beans with Dependent Value Objects, http://www.theserverside.com/patterns/depbmp.jsp.

6  IBM Redbook, Design and Implement Servlets, JSPs, and EJBs for IBM WebSphere Application Server , SG24-5754-00, http://publib-b.boulder.ibm.com/Redbooks.nsf/RedbookAbstracts/sg245754.html.

7  Design Patterns: Elements of Reusable Object-Oriented Software, Gamma, et al

8  Lazy Evaluation, Portland Pattern Repository, http://c2.com/cgi/wiki?LazyEvaluation.