Beans
N.B. Look at the JBeans web site for more information.

Reserved Properties

The following properties are reserved for JBeans:-

  • interface-Class getInterface() method gets the interface for the Bean.
  • primaryKey - an object that is the primary key.
  • primaryName - a user readable name for the bean.
  • modified - whether the bean has been modified, and needs persisting.
  • readOnly - whether the can be modified.
  • firingSuspended - whether bound or constrained events are fired.
  • timeStamp - the time the bean was last persisted.
  • persisted - whether the bean has been persisted.
  • validated - whether bean validation should be checked.

 

Interface

The getInterface() method is the significant method that allows the code to determine the primary interface for a Bean. Because can be implemented differently it is not possible to always determine the primary interface for a Bean at run time. The AbstractBean class can however hazard a guess (as the first interface in the class below itself), but this is not reliable.

Knowing the interface for a Bean allows code to find the Beans correct Session, Home and Validation from the Class Context at run-time.

Primary Name Property

The Bean class has a primary name, this defaults to class+pk.

This default will be overridden by any column with the name <ClassName>Name, for example a Table called Book may have a column called bookName.

These defaults can be overridden by specifying a simple Java expression: -

<ClassName>.primaryName=<Java expression>

For example:-

Person.primaryName=firstName + " " + lastname;

Indexable Property

The indexable property creates some extra methods for many-one relationships

public int get<ClassName>Count()

public <ClassName> get<ClassName>(int index )

and if the table has a toPrimaryName() then

public <ClassName> indexOf<ClassName>( String primaryName )

 

Modified Property

The modified property is used to determine whether the bean has been modified. This is used by some of the Home classes to determine whether to persist the bean to its store. Once a bean has been persisted it's modified property is set to false.

Accessor Properties

set and get/is methods are added for every property. Each method is fully documented.

For example a the method signatures for a property called age would be written as: -

public int getAge();

public void setAge( int age ) throws ValidationException;

Every setter method throws a ValidationException.

Where are property is nullable on the database an Object value is used, where a property is non-nullable on the database a primitive value is used. Simply changing the nullable property on the database will change the type of the property. For example if a property if the age property was optional the method signature would be written as: -

public Integer getAge();

public void setAge( Integer age );

This default type behavior can be overridden by the PropertiesReader.

Set and is/get methods are added for primary keys.

Where the property is another bean, with a zero-one or one-one relationship, it is the other Bean and not the primary key that is set on the Bean. For example if a Car class had an Engine property then the following methods would be written on the Car class: -

public Engine getEngine();

public void setEngine( Engine engine);

Transforming Properties

It is possible to transform properties when they are set on the bean. The syntax for doing this is as follows: -

<ClassName>.<propertyName>.transform=<expression>

For example: -

MyTable.myColumn=String.toUpperCase( String.trim( % ) );

This will create the following code in the setter property: -

myColumn = String.toUppercase( String.trim( myColumn ) );

Another common requirement in web application is that an empty strings should be converted to nulls, this is true for alot of web application servers that treat a null as an empty string. To get this behaviour for a single property use the syntax: -

<ClassName>.<propertyName>.emptyAsNull=true

To get this behaviour for the whole of a table use the syntax: -

<ClassName>.emptyAsNull=true

To get this behaviour across the whole database, use the syntax: -

emptyAsNull=true

Relationship Properties

Similar to Accessor Properties, Relationship Properties refer to relationships between Beans of a zero-many or zero-one relationship. Where a Bean has a relationship one bean will have a set/get method and the other bean will have add/remove properties.

For example two classes Car and Wheel, the Wheel class would have following methods written: -

public Car getCar();

public void setCar( Car car ) throws ValidationException;

The Car class would have the following methods written: -

public void addWheel( Wheel wheel );

public void removeWheel( Wheel wheel );

public Enumeration getWheels();

public void clearWheels();

The code generator handles the recursive referencing between the related beans, so that setting a car on a wheel is the same as adding a wheel to a car.

Transient Members

By default all the member variables that are beans, or vectors are transient by default. Primitive types are not transient by default. This is to allow beans to be serialized independently, either over the wire or down to disk independently. The Lazy Bean foreign keys are not transient. This mean s

To make a member variable transient use the following syntax: -

<ClassName>.<propertyName>.transient=true

To make a member variable transient use the following syntax: -

<ClassName>.<propertyName>Transient=false

Default Values

Defaults can also be specified in the properties file. This adds in-line Java code to the constructor.

<ClassName>.<propertyName>.default=<Java Value>

For example: -

User.amount.default=1.45
User.loginCount.default=1
User.password.default="password"

Bound Properties

Bound properties are properties that fire property change events. Events are only constructed and fired when somebody is listening.

By default properties are not bound. To make a property unbound, use the following syntax: -

<ClassName>.<propertyName>.bound=false

For example: -

Room.width.constrained=true

Constrained Properties

Constrained properties are properties that fire VetoableChangeEvents and reverse any changes by handling PropertyVetoExceptions. Events are only constructed and fired when somebody is listening.

By default properties are not constrained. To make a property constrained, use the following syntax: -

<ClassName>.<propertyName>.constrained=true

For example: -

Room.width.constrained=true

Array Properties

Array properties are properties that are arrays of primitive values, such as Arrays of Strings, Dates, int, long, boolean, or Enumerated Types

The Bean interface is the same as that of a foreign key (i.e. addX(X x)/removeX(X x)/get()/clear()). Where get() can return an Array, Iterator or Enumeration.

By default array properties are written down to a database as a TEXT field.

By default properties are not arrays.

arrays can be speficied by declaring [] after the variable name , for example:

readColumn.ObjectArray.20=dateTimeType[] DATETIME NULL

To make a property an array, use the following syntax: -

<ClassName>.<propertyName>.array=true

For example: -

Room.dates.array=true

By default properties are mapped to TEXT. This can be altered to be a VARCHAR type if you know it will not grow beyond the capacity.

<ClassName>.<propertyName>.array.type=VARCHAR(255)

 

Validated Properties

When any property is set, by default, a validation method is called on the validator, which could throw a ValidationException. Validators are automatically generated, and offer a powerful barrier to dirty data being set on the beans. For example if a car registration is set then a method called on the car validator the following line of code is generated: -

carValidator.validateRegistration( this, registation, "registration" );

This validation can be switched off for individual beans by setting the isValidated() method.

If the validation is not required by default for a bean , use the following syntax: -

<ClassName>Validated=false

If validation is never required for a property, it can be omitted, using the following syntax: -

<ClassName>.<propertyName>.Validated=false

Custom Validators can be added to the

ClientProperties

Client Properties are 'custom' properties set on the bean. They are basically key-value pairs and allow data to be flexibly added. Because they are not type safe they are not recommended for applications as a long term fixed solution. Given a code generator is at hand it is wiser to use this.

Every bean has a few methods to set and get client properties.

public Map getClientProperties() throws ValidationException;

public Object getClientProperty( Object key ) throws ValidationException;

public void putClientProperty( Object key, Object value ) throws ValidationException;

public void putClientProperty( Object key, Object value, boolean firePropertyEvent ) throws ValidationException;

Comparing Beans

Every bean is by default Compable, but assumes no sort order.

To make a bean comparable specifying the following will add a public int compareTo( Object object ) method with the following code.

<Class>.compareTo=<code>

The com.javelin.util.DefaultComparator has some static methods that can be used to help sorting. For example

House.compareTo=return DefaultComparator.compare( this.getPrimaryName(), ((Bean)object)getPrimaryName() );

listRelations

The listRelations method is responsible for populating a vector with the beans related to this bean. The method is used to determine which other beans should be saved, created or loaded. The list is a set therefore duplicate values are not added, and an attempt to add a duplicate value breaks the recursive descent.

The listRelations bean has the following signature: -

public void listRelations( Vector list, int type ) throws ValidationException;

The set of relations is determined by the type. The type can be one of :

Bean.ASSOCIATES
Bean.DEPENDENTS
Bean.RELATIONS (both associates and dependents)

The Lazy beans can also keep track of the removed associates and dependents. The lazy bean does this because it is (one possible bean) responsible for persistence.

Bean.REMOVED_ASSOCIATES
Bean.REMOVED_DEPENDENTS
Bean.REMOVED_RELATIONS (both associates and dependents)

The beans are added to the list is in the same order that they would be updated, or removed, and the reverse order that they would be created.

By default the associates and dependents are added. This can be switched off using the following syntax:

[[<Table>.]<propertyName>.]list[Associates|Dependents|RemovedAssociates|RemovedDependents]=false


The example below means that the Home beans associated with Address homeKey are never listed :

Address.home.listAssociates=false

Address.listAssociates=false

listAssociates=false


Exposing Lists

It is sometimes necessary to expose the underlying relationship between 2 beans as a list.

<class>.<property>.exposeRelationshipList=true

For example if the Room has a DEPENDENTS or ASSOCIATES relationship with a House

readColumn.Room.1=house INTEGER NOT NULL ASSOCIATES House

Room.house.exposeRelationshipList=true

Will create the following method on the House class

public void listRooms() throws ValidationException

This property can also be set at the class and project level.

<class>.exposeRelationshipList=true

exposeRelationshipList=true

Sort Relationship List

It is sometimes necessary to keep the relationship list sorted automatically, so that when any propert changes that affects the sort order list is resorted, when the database is saved. This keeps the cache in line with the database, without having to do back to the database to get the resorted data. Setting this property automatically exposes the relationship list.

<class>.<property>.sortRelationshipList=true

This property can also be set at the class and project level.

<class>.sortRelationshipList=true

sortRelationshipList=true

 

Adding Methods

Methods can be added to interfaces or classes. This true for Beans, Homes, Sessions or Validators.

Methods can be specified in the properties file.

<ClassName>.method.<Index>=<Full Method Declaration>
<ClassName>.code.<Index>=<Full Method Declaration>

This example adds in-line Java code to the ProductBean class.

Product.method.0=public void calculate( double value )

ProductBean.method.0=public void calculate( double value )
ProductBean.code.0=return CalculationLibrary.calculate( value );

If the method is abstract then the class becomes abstract and an user-defined binding needs to be added to the plugin ContextProperties. The user-defined binding can simply extend the generated implementation and add the implementation of the abstract methods.

This example creates a method on the Product class that is abstract on the ProductBean.

Product.method.0=public void calculate( double value )
ProductBean.method.0=public abstract void calculate( double value )

The ProductBean is now abstract so that a user defined binding must be added. In this case to the Jdbc (2-tier)

Context.Product.jdbc.Bean=com.mycompany.myproject.MyProduct

N.B. By not specifying the method property the code is implicitly added as part of the constructor. To make the custom code a static initializer then simply name the method as

ProductBean.method.0=static

To include a more complex method in-line from a relative file specify the following: -

ProductBean.method.0=public void calculate( double value )
ProductBean.code.0=$INCLUDE com.javelin.MyBean#PropertyBean_calculate.javafrag

To include a more complex method in-line from an absolute file specify the following: -

ProductBean.method.0=public void calculate( double value )
ProductBean.code.0=$INCLUDE C:/mycodefrags/calculate/PropertyBean_calculate.javafrag

 

Changing extends and implements

It is possible to simply add interfaces to Beans when calling the $CREATE CREATOR method

You can extend an interface or extend or implement on a class using the following syntax, to override the existing extension or implements

<ClassName>.extends=<className>, <className>
<ClassName>.implements=<className>, <className>

For example to change the extends and implments properties on the JdbcXXXX bean

JdbcXXXX.extends=com.yyy.MyJdbcInterceptor
JdbcXXXX.implements=com.yyy.MyMarkerInterface,com.yyy.MyOtherMarkerInterface

To change the interface: -

com.yyy.XXXX.extends=com.yyy.MyJdbcInterceptor,java.io.Serializable

Using the following syntax to append an interface: -

<ClassName>=$CREATE <CREATOR TYPE>, $SELF=$INTERFACE <Interface>

For example, if we had 3 tables (Country, State, City) that were all Locations we could put a Location interface on them: -

Country=$CREATE $CREATOR, $SELF=$INTERFACE $PACKAGE.Location
State=$CREATE $CREATOR, $SELF=$INTERFACE $PACKAGE.Location
City=$CREATE $CREATOR, $SELF=$INTERFACE $PACKAGE.Location

Adding Members

Member can be added to any interfaces or classes.

<ClassName>.member.N=<Full In-line Member Declaration>

For example: -

ProductBean.member.0=public final static STRING NUMBER = "123";
ProductBean.member.1=public final static STRING TEXT = "ABC";

Object Methods

A toString method is automatically written.

A hashcode for the bean is automatically written.

An equals for bean based on its class and primary key is automatically written.

Example Bean

Here is a (simple) example of an Address Bean, to give the big picture of what is generated: -

/*
* Copyright Javelinsoft Ltd, All rights reserved.
*/

package com.javelin.jcommerce;

import java.util.*;
import java.sql.*;
import com.javelin.jcommerce.*;
import com.javelin.jcommerce.*;
import com.javelin.beans.*;

/**
* Address.java
*
* @version JCommerce - 1.0
* @author Javelin Software
* @see com.javelin.jcommerce.AddressHome
* @see com.javelin.jcommerce.AddressSession
* @see com.javelin.jcommerce.AddressValidator
* @see com.javelin.jcommerce.AddressBean
* @see com.javelin.jcommerce.lazy.LazyAddressBean
*/

public interface Address extends Bean, Cloneable
{

/**
* Get the Address Key.
* @return Integer or null if it has not been set.
*/
public Integer getAddressKey();

/**
* Set the Address Key.
* @param addressKey The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setAddressKey( Integer addressKey ) throws ValidationException;

/**
* Get the Location.
* @return Location or a default value of null if it has not been set.
*/
public Location getLocation();

/**
* Set the Location.
* @param location The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setLocation( Location location ) throws ValidationException;

/**
* Get the First Name.
* @return String or a default value of null if it has not been set.
*/
public String getFirstName();

/**
* Set the First Name.
* @param firstName The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setFirstName( String firstName ) throws ValidationException;

/**
* Get the Last Name.
* @return String or a default value of null if it has not been set.
*/
public String getLastName();

/**
* Set the Last Name.
* @param lastName The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setLastName( String lastName ) throws ValidationException;

/**
* Get the Email.
* @return String or a default value of null if it has not been set.
*/
public String getEmail();

/**
* Set the Email.
* @param email The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setEmail( String email ) throws ValidationException;

/**
* Get the Line1.
* @return String or a default value of null if it has not been set.
*/
public String getLine1();

/**
* Set the Line1.
* @param line1 The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setLine1( String line1 ) throws ValidationException;

/**
* Get the Line2.
* @return String or null if it has not been set.
*/
public String getLine2();

/**
* Set the Line2.
* @param line2 The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setLine2( String line2 ) throws ValidationException;

/**
* Get the City.
* @return String or a default value of null if it has not been set.
*/
public City getCity();

/**
* Set the City.
* @param city The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setCity( city city ) throws ValidationException;

/**
* Get the State.
* @return String or a default value of null if it has not been set.
*/
public String getState();

/**
* Set the State.
* @param state The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setState( String state ) throws ValidationException;

/**
* Get the Post Code.
* @return String or a default value of null if it has not been set.
*/
public String getPostCode();

/**
* Set the Post Code.
* @param postCode The value to set.
* @exception ValidationException If there was a problem validating the value.
* @see com.javelin.jcommerce.AddressValidator
*/
public void setPostCode( String postCode ) throws ValidationException;

/**
* Clone bean without throwing an Exception.
*/
public Object clone();
}