Component-Oriented Thinking (Page 3)
<< Page 2 (Component Oriented Thinking)
<< Back to the start
Data Binding
Related to this problem of data persistence API bloom is that of
data binding. Data binding is the idea that data objects can be
bound to a database or a user interface to provide integration.
Data binding is a concept from the world of VB and Delphi.
Most of all, data binding is useful. You point an object
at a database and a UI and tell the UI to display and edit the object.
That was all there really was to it. Data binding is useful because
it's what developers do most of the time. The idea is that you should
ensure that the default behaviour of a system is what you most want
it to do.
Java never really got data binding. Java Beans got partially there
by defining property editors and property change events. Even in
the latest version of Swing, Java creeps towards data binding at
a snail's pace with the JFormattedTextField and InputVerifier. So
what would have happened if the Beans specification had shifted
towards component oriented software rather then supporting integrated
development environments?
At Javelin Software we addressed this problem by developing a standard
called JBeans. JBeans were
developed as a natural component-oriented extension of the Java
Beans standards.
For example, imagine a Person Bean and a Person Session. The Person
Bean has the following methods:
public interface Person extends Bean
{
public Integer getPersonKey();
public void setPersonKey( Integer personKey ) throws ValidationException;
public String getTitle();
public void setTitle( String title ) throws ValidationException;
public String getFirstName();
public void setFirstName( String firstName ) throws ValidationException;
public String getLastName();
public void setLastName( String lastName ) throws ValidationException;
public Address getAddress();
public void setAddress( Address address ) throws ValidationException;
}
To fully implement this bean along with all the validation, bound
properties, event firing,
recursive checks, comments etc, involves a lot of coding. The actual
information in the
interface could be distilled down into 5 type declarations. In our
experience the ratio of
implementation code to meta data declaration is between 20-50 to
1. A huge inefficiency.
The Person Session is similarly declared. The Person Session also
has a number of business behaviours, namely persistence and retrieval.
The actual information in the session interface can be distilled
too. By default a Bean should be persistable, therefore the load,
save and remove object could be created. The retrieval methods likewise
can be assumed. Methods to find by primary key and find all, as
well as find by query could be assumed. The find by Address method
could also be assumed, as the Person object references that object,
and this method would be used if the Address were to be loaded in
a lazy fashion. Find bys could also be assumed to be created for
any index.
public interface PersonSession extends BeanSession
{
public Enumeration findByAll() throws FinderException, ValidationException;
public Person findByAddress( Object addressKey ) throws FinderException, ValidationException;
public Person findByPrimaryKey( Object personKey ) throws FinderException, ValidationException;
public Enumeration findByQuery( String query ) throws FinderException, ValidationException;
public Enumeration findByQuery( String query, int maxRows ) throws FinderException, ValidationException;
public int countByQuery( String query ) throws FinderException, ValidationException;
public void load( Person person ) throws LoadException, ValidationException;
public void save( Person person ) throws CreateException, StoreException, ValidationException;
public void remove( Person person ) throws RemoveException, ValidationException;
}
Beans are instantiated using standard factory classes. The interface
does not dictate how the bean is implemented; it could be implemented
using proxies or jni. For example:
PersonSession personSession = ClassContext.newPersonSession();
Person person = ClassContext.newPerson();
person.setFirstName( "Robin" );
person.setLastName( "Sharp" );
personSession.save( person );
JBeans make the separation between data (beans) and architecture
(sessions), and between interfaces and implementation. JBeans is
supported by JGenerator,
a code generator that allows the creation of component oriented
architectures. JBeans allows developers to transparently migrate
between 1-tier (in-memory or files), 2-tier (JDBC, JDO or EJB) and
3-tier (EJB) implementations.
JBeans is also supported by JEditor, a standard set of editors,
that allow data binding between Swing components
and the JBeans components.
To create a form and bind the UI components to the bean properties
the effort should be minimal. For example:
public class PersonEditor
{
...
protected PropertyBindingManager pbm = new PropertyBindingManager();
protected void init( Person person )
{
...
editorPanel.add( pbm.newCustomLabel( person, Person.TITLE ) );
editorPanel.add( pbm.newCustomEditor( person, Person.TITLE ) );
editorPanel.add( pbm.newCustomLabel( person, Person.FIRST_NAME ) );
editorPanel.add( pbm.newCustomEditor( person, Person.FIRST_NAME) );
editorPanel.add( pbm.newCustomLabel( person, Person.LAST_NAME ) );
editorPanel.add( pbm.newCustomEditor( person, Person.LAST_NAME ) );
editorPanel.add( pbm.newCustomLabel( person.getAddress(), Address.LINE1 ) );
editorPanel.add( pbm.newCustomEditor( person.getAddress(), Address.LINE1 ) );
editorPanel.add( pbm.newCustomLabel( person.getAddress(), Address.LINE1 ) );
editorPanel.add( pbm.newCustomEditor( person.getAddress(), Address.LINE1 ) );
editorPanel.add( commitButton );
commitButton.addActionListener( new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
PersonEditor.this.pbm.commit();
}
} );
}
...
}
The usefulness of JBeans, JGenerator and JEditors shows that data
binding can be achieved allowing data to be bound between different
Java UIs and persistence architectures. In JBeans, data and architecture
are first class types in a 'virtual' programming language. We can
then use JGenerator's compiler to render the business functionality
into different persistence layers. JBeans does not expose implementation
details such as JDBC, EJB or UserTransactions, nor should it. Getting
the API's correct is not that difficult (JBeans follows some of
the EJB naming patterns for the architecture API's) but just having
those patterns in place provides a springboard for transparent data
binding tools to be developed.
>>
Page 4 (Domain Oriented Software & Conclusion)
<< Back to Programming
<< Back to Software Reality
|