Thursday, April 21, 2011

Beans binding with human face

In my previous article I've showed how to easily compose swing forms with html markup. Since that time my swinghtmltemplate library moved to version 0.3 with beans binding support. Here I'll show basic examples of using binding.


Binding is the process of synchronizing the value of two properties. Concerning to swing this allows, for example, to keep in sync the «text» property of JTextField with «name» property of Person. You can read more on binding here.

Add the library using maven:

<dependencies> 
   <dependency> 
      <com.googlecode.swinghtmltemplate</groupid>
      <artifactid>swinghtmltemplate</artifactid>
      <version>0.3</version>
   </dependency>
</dependencies>
<repositories>
   <repository>
      <id>swinghtmltemplate</id>
      <name>Swing html template repo</name>
      <url>http://swinghtmltemplate.googlecode.com/svn/maven-repository</url>
      <releases>
         <enabled>true</enabled>
         <updatepolicy>never</updatepolicy>
      </releases>
      <snapshots>
         <enabled>false</enabled>
      </snapshots>
   </repository>
</repositories>

You can also download distributive with dependencies.

Let's create domain object — person. It has two properties: name and email.

public class Person {
   private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
   private String name;
   private String email;
 
   public String getName() {
      return name;
   }
 
   public void setName(String name) {
      Object old = this.name;
      this.name = name;
      pcs.firePropertyChange("name", old, name);
   } 

   public String getEmail() {
      return email;
   } 

   public void setEmail(String email) {
      Object old = this.email;
      this.email = email;
      pcs.firePropertyChange("email", old, email);
   } 

   public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcs.addPropertyChangeListener(listener);
   } 

   public void removePropertyChangeListener(PropertyChangeListener listener) {
      pcs.removePropertyChangeListener(listener);
   } 
}

We want to make form with 2 input fields and bind them to name and email properties.

To specify binding, you must do 2 things:

  • provide dom model with model values
  • specify binding for component

The first task can be done with:

DomModel domModel = ...;
model.addModelElement("person", new Person());

Now the person object is passed to the dom model under the «person» key, so you can use it with ${person}

If you have controller for you form, when you can provide model values with @ModelAttribute annotation.


Let's create controller for our form:

package foo;
 
...//imports
 
public class PersonForm extends JPanel {
   private DomModel model;
   
   @ModelElement("person")
   private Person person = new Person();    

   public PersonForm() {
      try {
         model = Binder.bind(this, true);
      }
      catch (JDOMException e) {
         e.printStackTrace();
      }
      catch (IOException e) {
         e.printStackTrace();
      }
   } 

   public Person getPerson () {
      return person;
   } 

   public void setPerson (Person person) {
      Object old = this.person ;
      this.person = person;
      firePropertyChange("person", old, person);
   } 

   public void onOK() {
      System.out.println(person.getName()+" "+person.getEmail());
   } 

   public static void main(String[] args) throws JDOMException, IOException {
      PersonForm personForm = new PersonForm();

      Person person = new Person();
      person.setName("John Doe");
      personForm.setPerson(person);

      JFrame f = new JFrame("Test");
      f.setSize(400, 200); 
      f.getContentPane().add(personForm);
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setVisible(true);
   } 
} 

You can see we pass our domain object to the dom model under the «person» name. Model is filled when Binder.bind(this, true); is invoked, so you can prepare domain values before this call.

Also notice we are firing a property change in setter. This is usual java bean routine.

In the main method we create an instance of our controller, place in in JFrame. We also create an initial person with specified name.

Next let's create form and see how to bind it to person:


We place this code in «/src/foo/PersonForm.html».

Look at the input tags. We specify binding in the «value» attribute. First input is binded to the person's «name» property, second — to the «email» property. The binding is bidirectional, so changing text in the input fields will update person, and changing person's properties will update text fields.

We added a button to the panel — the last input. It has attribute 'onclick' with the value «onOK». This means that the «PersonForm.onOK()» will be invoked when clicking on the button.

You can try the example, enter some text, press button and see that the person's properties are changed.

No comments :

Post a Comment