Basic Data Beans

Data Beans are "packages" of information that provide a convenient mechanism for passing a set of closely related variables -- for example, variables corresponding to the fields of a form -- from one method, class, or machine to another. 

Data beans normally include a set of getter and setter methods that provide a public interface to its variables. 

In addition,  data beans often contain supporting logic, such as ensuring that certain required data is present  or checking the variables for consistency or completeness.  For example, a data bean could check to see that a field that serves as the primary key of a database table is non null. 

They may also include methods that map from one representation of the bean's data to another, such as returning its variables as a HashTable or as a protocol.

Data beans are not, however, a well-defined Java class or package.  Rather, they represent a "best practices" option that is appropriate for a number of architectures, particularly layered and distributed architectures.

The discussion below is, thus, general but will use the Address Book problem as an example.


Motivation

Consider the architecture of a layered Java Servlet.

The following (incomplete) applet, which could be a client for the layered Servlet referenced above, illustrates some of the function associated with data beans.

Run ABApplet


Specific Beans

Whereas many applications will sue only a single data bean class, some designs may include several different data bean classes.  These classes may be independent of one another or one bean may extend another, adding special-purpose methods and functions appropriate for one level of a layered architecture but not another.

Example

The ABApplet uses two data beans:

The EntryObj bean includes only the variables that correspond with the input and output fields of the form.  

The TransObj bean extends EntryObj and includes a method field that could be used as part of a protocol message.


Variables

A data bean normally includes a set of closely related variables.  In this case, the variables correspond to the fields in a data input form and they are the very same data that might be required by another class or method that next processes those data.

Example

The EntryObj bean includes only the variables that correspond with the input and output fields of the form.  

    public class EntryObj {
	private java.lang.String name;
	private java.lang.String address;
	private java.lang.String comment;
	private java.lang.String returncode;
	

The TransObj bean extends EntryObj and includes a method field that could be used as part of a protocol message.

    public class TransObj extends EntryObj {	
	private java.lang.String method;
 

Getters and Setters

To provide public access to the variables, data beans include getter and setter methods, a pair for most but only getter methods for those that are "read only."

Example

    public java.lang.String getName() {
	return name;
        }
    public void setName(java.lang.String newName) {
	name = newName;
	}

Data Integrity and Constraints

A data bean is an excellent place to check that required fields have values and that other fields are in appropriate ranges or formats. The most obvious reason is that if it can be done when the bean is first created it is obviously more efficient than waiting until the bean has passed through several other layers unnecessarily before checking.

Types of checks include verifying that key fields have non-null values, that "today's date" is not next week, and that an account balance is greater than zero before authorizing a purchase. 

Example

In this example, only a single field is checked for a non-null value.

    public boolean isValid() {
	if ( (name ==null) || name.equals("") ) return false;
	else return true;
	}

Data Mapping

Data beans often provide "mapping" functions, transforming their data from one format or representation to another.  One common type of mapping is transforming Java variables to and from fields in a table in a database.  But other mappings are also common.

Example

In this example, several types of mapping are provided.  Mappings can be done both through access methods and through a constructor in which initial values intended for the bean's variables are presented in different forms.

The example starts with the default constructor, whic takes no ilnitial varialbes (and, hence, would rely on setter methods for setting values).

    public TransObj() {
	super();
	}

An alternative constructor sets the values for the variables using an EntryObj.  Thus it maps from EntryObj to TransObj.

    public TransObj(EntryObj eObj) {

	super();
	
	this.setName ( eObj.getName() );
	this.setAddress ( eObj.getAddress() );
	this.setComment ( eObj.getComment() );
	this.setReturncode ( eObj.getReturncode() );
		
	}
	

Since TransObj extends EntryObj, a TransObj bean can be mapped  into an EntryObj instance by casting.  But, of course, you can't cast the other way.  Why?

	EntryObj eObjo = (EntryObj)tObj;

Another alternative constructor sets the values for the variables using a protocol string.  Thus it maps from protocol to TransObj.

    public TransObj(String protocol) {
	
	super();

	Hashtable ht = HttpUtils.parseQueryString ( protocol );

	
	if ( ht.containsKey ( "name" ) ) this.setName ( (String)ht.get( "name" ) );
	if ( ht.containsKey ( "address" ) ) this.setAddress ( (String)ht.get( "address" ) );
	if ( ht.containsKey ( "comment" ) ) this.setComment ( (String)ht.get( "comment" ) );
			
	if ( ht.containsKey ( "method" ) ) this.setMethod ( (String)ht.get( "method" ) );
	if ( ht.containsKey ( "returncode" ) ) this.setReturncode ( (String)ht.get( "returncode" ) );
			
	}
	

In addition to constructors, the bean may provide methods that return data in a particular form.  In this example, three forms of protocol stream are supported:

The three differ with respect to whether or not method and returncode components are included in the protocol string.

    
    public String getDataProtocol() {


	String r = new String();

	r += "name"  + "=" + URLEncoder.encode( this.getName() );
	r += "&" + "address"  + "=" + URLEncoder.encode( this.getAddress() );
	r += "&" + "comment"  + "=" + URLEncoder.encode( this.getComment() );
	
	return r;

	}

 

    	public String getRequestProtocol() {
	
	String r = new String();

	r += "method"  + "=" + URLEncoder.encode( this.getMethod() );
	r += "&" + getDataProtocol();

		
	return r;

	}
    
        public String getResponseProtocol() {

	String r = new String();
		
	r += "returncode"  + "=" + URLEncoder.encode( this.getReturncode() );
	r += "&" + getDataProtocol();

	return r;
			
	}
        

Comment

This is very simple programming.  The data beans include a good many variables and methods, but each is easily written and there is a lot of overlap within each.

In another lesson, I suggested that you should include in your design six or eight "helper methods."