Software Reality
Programming with
a dose of satire.

Site Map Search


Agile Development
 
Extreme Programming
 
Code Generation


Articles
Lifecycle
Design
Programming
Soapbox
Reviews
Cthulhu

Java Swing
Swing's greatest threat isn't SWT, it's Flash
Swing Survival Guide


 
Check out our ageing Reviews Section


Use Case Driven
Use Case Driven Object Modeling with UML: Theory and Practice
Get from use cases to working, maintainable source code. Examples use Spring Framework, JUnit and Enterprise Architect

Agile UML
Agile Development with ICONIX Process
A practical subset of agile development techniques, illustrated by example

Get Controversial!
Extreme Programming Refactored
Extreme Programming with a dose of satire
Available now:



Programming

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

All trademarks and copyrights on this page are owned by their respective owners.
Stories and articles are owned by the original author.
All the rest Copyright © 1998-2008 Matt Stephens. ALL RIGHTS RESERVED.