My favorites | Sign in
Project Logo
                
Search
for
Updated Oct 23, 2008 by Yegor.Jbanov
Labels: Featured
Tutorial  
A very quick tutorial (0.2)

Introduction

This tutorial will guide you through creation of a very simple GUI project. The goal of this tutorial is to give you an idea of how client-objects library can help you with the development of GUI applications using one of the (arguably) most common use-cases. At the end of the tutorial you will know what jar files constitute the library, their dependencies and how to add everything to your project.

Prerequisites:

Project Setup

Fire up your Eclipse IDE and start a simple Java project. By default Eclipse will put your source folder and compiled classes into the root of the project folder. I like separating these things. I also like to keep 3rd-party libraries in a separate folder. So:

Download Dependencies

Open your favourite browser (this step works only with the favourites) and direct it to:

http://code.google.com/p/client-objects/downloads/list

Download one of the archives (zip for windows, tar.gz for linux) into a folder of your choice and extract the files. You should see the following files:

  • client-objects-0.2.jar - This is the only client-objects library
  • client-objects-samples-0.2.jar - Contains samples
  • client-objects-test-0.2.jar - Contains JUnit test cases
  • lib - this folder contains all the dependencies including test-time libraries (JUnit) and libraries used in the samples (JGoodies Binding, JGoodies Forms). The libraries required by the client-objects framework are only asm and cglib.

For this tutorial you will need client-objects-0.2.jar, asm-1.5.3.jar, binding-1.3.0.jar, cglib-2.1_3.jar, forms-core-1.1.0.jar. Copy them all into your Eclipse project's lib folder created at step 'Project Setup'.

Go to project properties -> Java Build Path -> Libraries and 'Add JARs...' from the lib folder into your project.

You are now ready to start coding.

GUI for a Customer Database

Suppose you need to write a GUI front-end to a customer database. Your GUI must communicate with a remote server using some sort of RMI (Java RMI, Web Services, XFire, etc). The server is already implemented and is using Hibernate (or EJB3, or iBATIS) for database access. A customer record is represented by a data class Customer. The class is a POJO, i.e. it encapsulates a bunch of data fields and provides getter and setter methods to access the fields. Here's the Customer class.

Customer Class

package com.spicesoft.clientobjects.tutorial;

import java.util.Date;

public class Customer {

  private String firstName;

  private String lastName;

  private Date birthDate;

  public Date getBirthDate() {
    return birthDate;
  }

  public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

}

TutorialApp Class

Our application will be receiving instances of this class from the server and must present the data in the objects to the user on the GUI. If the object was a JavaBean with property change support we could use the JGoodies Binding framework to help us link property values to the GUI elements. Unfortunately the Customer class is just a POJO with no property change support. This is where client-objects framework comes in. It will convert our POJO into a JavaBean compatible with any JavaBean-related framework, including JGoodies Binding.

Consider the following implementation of the GUI.

package com.spicesoft.clientobjects.tutorial;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import com.jgoodies.binding.adapter.BasicComponentFactory;
import com.jgoodies.binding.beans.PropertyAdapter;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.spicesoft.clientobjects.BeanEnhancer;
import com.spicesoft.clientobjects.BeanRegistry;

public class TutorialApp extends JFrame {

  public static void main(String[] args) {
    // Register POJOs
    BeanRegistry.registerType(Customer.class);

    // Create Customer POJO
    Customer pojo = new Customer();
    pojo.setFirstName("Yegor");
    pojo.setLastName("Jbanov");
    pojo.setBirthDate(new Date());

    // Convert POJO to JavaBean (i.e. add property change support)
    Customer bean = BeanEnhancer.addPropertyChangeSupport(pojo);

    // Create application frame and pass the customer bean to operate on
    TutorialApp appFrame = new TutorialApp(bean);
    appFrame.pack();
    appFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    appFrame.setLocationRelativeTo(null);
    appFrame.setVisible(true);
  }

  public TutorialApp(Customer bean) {
    this.setTitle("Customer Information");
    JPanel cp = new JPanel();
    FormLayout layout = new FormLayout("5dlu, p, 5dlu, 100dlu:g, 5dlu",
        "3dlu, p, 3dlu, p, 3dlu, p, 3dlu, p, 3dlu");
    CellConstraints cc = new CellConstraints();
    cp.setLayout(layout);
    this.setContentPane(cp);
    
    // Create and bind fields
    PropertyAdapter firstNameA = new PropertyAdapter(bean, "firstName", true);
    JTextField firstNameF = BasicComponentFactory.createTextField(firstNameA, true);
    JLabel firstNameL = new JLabel("First Name");
    cp.add(firstNameL, cc.xy(2, 2));
    cp.add(firstNameF, cc.xy(4, 2));
    
    PropertyAdapter lastNameA = new PropertyAdapter(bean, "lastName", true);
    JTextField lastNameF = BasicComponentFactory.createTextField(lastNameA, true);
    JLabel lastNameL = new JLabel("Last Name");
    cp.add(lastNameL, cc.xy(2, 4));
    cp.add(lastNameF, cc.xy(4, 4));
    
    PropertyAdapter birthDateA = new PropertyAdapter(bean, "birthDate", true);
    JTextField birthDateF = BasicComponentFactory.createDateField(birthDateA);
    JLabel birthDateL = new JLabel("Birth Date");
    cp.add(birthDateL, cc.xy(2, 6));
    cp.add(birthDateF, cc.xy(4, 6));
    
    // Create close button
    JButton closeBtn = new JButton("Close");
    closeBtn.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        TutorialApp.this.dispose();
      }
    });
    cp.add(closeBtn, cc.xy(4, 8));
  }

}

First we need to tell the client-objects framework which classes will be enhanced in the course of program's execution. We need to do this in advance because some POJOs may encapsulate other POJOs, so when a parent POJO is converted into a JavaBean the child POJO is converted recursively as long as both POJO classes are registered with the framework. The registration is static, i.e. global across the library's classloader.

    BeanRegistry.registerType(Customer.class);

For simplicity we create an instance of the POJO and populate it with hard-coded data. Normally the POJO will be downloaded from the server with all values in place.

    Customer pojo = new Customer();
    pojo.setFirstName("Yegor");
    pojo.setLastName("Jbanov");
    pojo.setBirthDate(new Date());

In the following line we convert the POJO into a JavaBean. Note that the resulting JavaBean is assignable to a Customer variable. This is because it actually extends the POJO. It also implements com.spicesoft.clientobjects.core.PropertyChangeListenerSupport interface which adds JavaBean-specific methods, that normally are missing in a POJO.

    Customer bean = BeanEnhancer.addPropertyChangeSupport(pojo);

Now we create the application's frame and bind the JavaBean to the GUI elements using JGoodies Binding framework. We also use the excellent JGoodies Forms library to create a nice layout.

The following two lines show how you can use the bean as you would use a classic JavaBean with the binding framework. In the first line, note how the firstName property of the Customer class is being bound to a JTextField.

    PropertyAdapter firstNameA = new PropertyAdapter(bean, "firstName", true);
    JTextField firstNameF = BasicComponentFactory.createTextField(firstNameA, true);

Now run the TutorialApp class as a Java application and observe how all the values defined in the POJO automatically appear in the text fields. This is a combined magic of JGoodies Binding and client-objects. As an exercise you can make sure that whenever you change a value in a text field is it instantly updated in the bean and vice versa.

Your Feedback

I am planning to keep this document as accurate as possible. If you notice any mistakes or ambiguities, have other suggestions, please feel free to submit a bug report.


Sign in to add a comment
Hosted by Google Code