Tip 4 - Strategies for Listing Behavior

September 25th, 1999
In chapter 7 of the book Enterprise JavaBeans (O'Reilly) some time is spent discussing listing behavior; methods that return lists of tabular data.  Tabular data is often used to select or otherwise peruse data in the system.  Enterprise JavaBeans provides a mechanism for listing entity beans in the find methods, but this mechanism is not a silver bullet.  In many circumstances we do not want to use find methods that return remote references.  Below is a quote from the book:
"The listAvailableCabins() method returns an array of Strings. This is important because we could have opted to return an enumeration of Cabin remote references, but we didn’t. The reason is simple: we want to keep the client application as lightweight as possible. A list of Strings is much more lightweight than the alternative, an Enumeration of remote references. In addition, a collection of remote references means that client would be working with many stubs, each with its own connection to EJB objects on the server. By returning a light-weight string array, we reduce the number of stubs on the client, which keeps the client simple and conserves resources on the server."
Simple Array

The strategy used in the book is called a simple array strategy for listing behavior.  Essentially any set of tabular data (data organized into rows and columns) can be represented in single or multidimensional arrays of String objects.  Imagine, for example, that you need to present the user with the cruise schedule for a specific cruise.  A cruise schedule consists of 4 columns of data and a row for each Port-Of-Call (below is an example data in tabular format).

Cruise ID Port-of-Call Arrive Depart
233 San Juan June 4, 1999 June 5, 1999
233 Aruba June 7, 1999 June 8, 1999
233 Cartagena June 9, 1999 June 10, 1999
233 San Blas Islands June 11, 1999 June 12, 1999
It would be possible to create a Port-Of-Call entity object which represents every destination and then obtain the data using a traditional find method, but this might be overkill.  Recognizing that the data is not shared and only useful in this one circumstance, we can present the data through a simple listing method as tabular data.

In this case we will present the data to the bean client as an array of String objects with the values separated by a character delimiter.  Below is an example of the method signature used to obtain the data and the structure of the String elements returned.

Structure of the String values returned by the listing method. Definition of the bean that uses the String array
233; San Juan; June 4, 1999; June 5, 1999 
233; Aruba; June 7, 1999; June 8, 1999 
233; Cartegena; June 9, 1999; June 10, 1999 
233; San Blas Islands; June 11, 1999; June 12, 1999
public interface HypotheticalSession { 

 public String [ ] getSchedule(int ID) 
    throws RemoteException; 

The data could also be returned in a multidimensional array where each column represents one dimension.  This would certainly make it easier to directly reference each data item, but would also complicate navigation.

One disadvantage to using the simple array strategy is that Java is limited to single type arrays. In other words, all the elements in the array must be of the same type.  We use String here, since it has the most flexibility for representing other data types.  Object type array could also be used or even a Vector.  The problem with using an Object array or Vector is that there is no typing information at run time or development time.

Structure Array

In addition to simple arrays, arrays of structures can also be returned.  To return the cruise ship schedule data illustrated above, you could return the data as an array of schedule structures; simple Java objects passed in an array. The definiton of the structure and the bean interface that would use are defined below:

Definition of the Structure Definition of the bean that uses the Structure
public class CruiseScheduleItem { 

    public int cruiseID; 
    public String portName; 
    public java.util.Date arrival; 
    public java.util.Date departure; 

public interface HypotheticalSession { 

 public CruiseScheduleItem [ ] getSchedule(int ID) 
    throws RemoteException; 

The advantage to using Structures is that the data elements can be of different types.  In addition, the structures are self describing; its easy to determine the structure of the data in the tabular set based on its class definition.


A more sophisticated and flexible solution is to provide a pass-by-value implementation of the java.sql.ResultSet interface.  Although it is defined in the JDBC package (java.sql) the ResultSet interface is semantically independent from relational databases.  A ResultSet interface can be used to represent any set of tabular data.   Since the ResultSet interface is well designed to represent tabular data and is familiar to most experienced enterprise Java developers it is an excellent construct for use in listing behavior.  Using the ResultSet strategy the above listing method, for example, would be redefined as follows.

Definition of the bean that uses the ResultSet
public interface HypotheticalSession { 

    public ResultSet getSchedule(int cruiseID) throws RemoteException; 

Implementation of the ResultSet interface

In some cases, the tabular data displayed at the client may be generated using standard SQL through a JDBC driver.  If the circumstances permit, you may choose to perform the query in a session bean and return the result set directly to the client through a listing method.  In many cases, however, you may not want to use a ResultSet that comes directly form JDBC drivers. The ResultSet from JDBC 1.x drivers are normally connected directly to the database which increases network overhead and exposes your data source to the client.  In these cases you can implement your own ResultSet object that utilizes arrays or vectors under the covers to cache the data.  JDBC 2.0 provides a cached javax.sql.RowSet which looks like a ResultSet but is passed by value and allows reverse scrolling among other things.  You can use this also but don't expose behavior that allows the result set to updated.  Data updates should be performed by bean methods.

In other cases, the tabular data comes from several data sources or non-relational databases.  In these cases you can query the data using the appropriate mechanisms within the listing bean, and then reformat the data into your ResultSet implementation.  Regardless of the source of data you still want to present it as tabular data using the ResultSet interface through a custom implementation.

Advantages of ResultSet

Consistent Interface for Developers
The ResultSet interface provides a consistent interface that developers are familiar with and that js consistent across different listing behaviors.  Developers don't need to learn several different constructs for working with tabular data; they use the same ResultSet interface for all listing methods.

Consistent Interface for Automation
The ResultSet interface provides a consistent interface that allows software algorithms to operate on data independent of its content.  A builder can be created that constructs an HTML or GUI table based on any set of results that implement the ResultSet.

Meta-Date Operations
The ResultSet interface defines several meta-data methods that provide developers with run time information describing the result set they are working with.

The ResultSet interface is independent of the data content which allows tabular sets to change their schema independent of the interfaces; a change in schema does not require a change to the method signatures of listing operations.

Disadvantages of ResultSet

The ResultSet interface strategy is much more complex than the simple or structure array strategies.  It normally requires you to develop a custom implementation of the ResultSet interface.  If properly designed the custom implementation can be reused across all your listing methods, but it's still a significant development effort.

Hidden Structure at Development Time
Although the ResultSet can describe itself through meta-data at run time, it can not describe itself at development time.  Unlike the simple array or structure array strategies the ResultSet interface provides no clues at development time as to the structure of the underlying data.  At run time meta-data is available, but at development time good documentation is required to express the structure of the data explicitly.

Back to Top