JFaceFactories- Quick Start

Let us say you have a business domain object:

  public class Person{
private String name;
// getter & setter...
}

For databinding to work you must able to bind to the domain object's properties; i.e. listeners must be notified whenever these properties change. You can add this functionality to the domain object direct (e.g. use java.beans.PropertyChangeSupport) or extend the AbstractPresenter class provided by JFaceFactories:

  public class PersonPresenter extends AbstractPresenter<Person>{
public static final String NAME_PROPERTY = "name";
public PersonPresenter( Person domainObject ) {
super( domainObject );
}
public String getName(){
return getDomainObject().getName();
} public void setName( String name ) {
setDomainObjectValue( NAME_PROPERTY, name );
}
}

Now you should write the JUnit TestCase for your new presenter class.

Once you have done this, you can get on with the GUI.

Create your JFace application and create a UI element for entering the person's name. Create an SWT Text box and bind it to the property on the presenter...

  ...
PersonPresenter presenter = new PersonPresenter( ... );
...
Text text = new Text( ... );
... Binders.getTextBinder().bind( presenter, PersonPresenter.NAME_PROPERTY, text );

That's it! You have been introduced to the 2 core classes of JFaceFactories:

  • AbstractPresenter - a base class for all your presenters
  • Binders - static access to all the binding functionality provided by JFaceFactories.

But, hold on, all we have done is added a (slightly tidier!) layer of indirection to the underlying JFace databinding. Is that it?

Well no. JFaceFactories allows you to do a lot more to control the UI behaviour - all by adding properties to your presenter classes. Let us say that you want to control whether or not a Person's name can be edited, depending on some complex business logic...

Add a property to the presenter:

  public class PersonPresenter extends AbstractPresenter<Person>{
public static final String NAME_PROPERTY = "name"; public static final String NAME_EDITABLE = "nameEditable";
... public boolean isNameEditable() { return doSomeComplexBusinessLogic(); } // no setter ... }

And add an additional binding in the UI creation:

   Binders.getEnableBinder().bind( presenter, PersonPresenter.NAME_EDITABLE, text );

So the UI remains simple whilst all the complex business logic resides in the presenter class which can be tested by JUnit.

The next step is to consider conditional properties - where one property depends on another. Such conditional properties are at the heart of creating complex, dynamic UI behaviour. Let us add a date of birth field to the Person - but only allow this to be edited once a name has been added...

You add the new field to the domain object and matching methods on the presenter:

  public class Person{
private String name; private Date dateOfBirth
// getters & setters...
} public class PersonPresenter extends AbstractPresenter<Person>{
... public static final String DOB_PROPERTY = "dateOfBirth"; public static final String DOB_EDITABLE = "dobEditable";
... public boolean isDobEditable() { return getName() != null; } // no setter ... }

On the UI you create a new DateTime control and bind this to these new properties:

    DateTime dob = new DateTime( ... );
    ...
    Binders.getDateTimeBinder().bind( presenter, PersonPresenter.DOB_PROPERTY, dob );
Binders.getEnableBinder().bind( presenter, PersonPresenter.DOB_EDITABLE, dob );

Now make the date of birth conditional on there being a name; on the presenter change the name setter:

    public void setName( String name ) {
      if ( name == null ) setDateOfBirth( null );
setDomainObjectValue( NAME_PROPERTY, name, DOB_EDITABLE );
}

The null check on name handles data consistency - there can be no date of birth without a name. The setDomainObjectValue(...) method now has a final vararg argument that lists all other properties that may be affected by the change. This will fire off events to all listeners and, here, ensure that the enablement of the 'dob' DateTime control is correct.

And that is the basic mechanism for creating dynamic, testable user interfaces with JFaceFactories. We aim to support all sorts of UI behaviour through a ranges of XXXBinder types and methods. Please see scope for what is currently available and what we plan to introduce.

The next step is to download the source and check out our small demo project. Have fun and, please, send us feedback via the forums.