Using JGoodies With Other Frameworks

Learn how to combine JGoodies with other backend frameworks in your desktop application. The main problem is the need to create objects that extend the Model class while other frameworks might consider this a problem, either because they require POJOs or provide other specific rules.

If you create GUIs using the JGoodies Binding library, you will probably have to create bean classes that extend the com.jgoodies.binding.beans.Model class.

If your desktop application also uses a framework for other purposes (e.g., persistency) and you plan to use the same model object from the GUI with this framework, then you will have to make sure you don’t have conflicting requirements.

This problem is reasonably common and happens because java doesn’t allow multiple inheritance. So, any framework that is used in conjunction with JGoodies and has rules for the target object (e.g., it must be a POJO), then the implementation starts to become more complex.

Let’s discuss one possible solution for those cases where the other framework requires the object to be a POJO (e.g., Hibernate, JPA, etc.). In such cases, we can create one class for the POJO (attributes + getters + setters) and another class that wraps this POJO, which has similar methods but has the advantage to execute other actions.

Example of a POJO:

public class Student {
    private String name;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

The POJO above can be used by the persistency framework without problems. Now we need a class to be used by the Binding library (GUI):

public class StudentModel extends Model {
    private Student student;

    public StudentModel(Student student) { this.student = student; }

    public String getName() { return student.getName(); }

    public void setName(String name) {
        String old = student.getName();
        student.setName(name);
        this.firePropertyChange("name", old, name);
    }
}

This isn’t a perfect solution, but solves the problem. One disadvantage is the maintenance required by the two sets of methods that access the POJO, which could be automated by a small piece of code that uses java reflection.

JGoodies Binding API: The Basics

Learn the basics of the JGoodies Binding API, which allows you to separate the application logic from UI components. This can lead to better code and strategic separation of concerns. This is the first relevant step towards the Presentation Model pattern.

The JGoodies Binding API offers a set of classes that helps the applicability of the Presentation Model pattern in java. It was developed on top of the Swing API and has some mechanisms to bind UI components to variables and objects that can be operated independently of their visual representations.

You can download the API from the JGoodies website. This and other libraries are available here. Inside the zip file you will find the source code, the documentation, examples and the JAR file you should add to your classpath to run the examples.

Now let’s study the idea behind this API. There are two basic cases that you must understand:binding components to single values and binding components to lists of objects.

Case 1 – Binding Components to Single Values

In order to better understand this binding idea, imagine that you have a boolean variable that is bound to a JCheckBox. This “connection” means that whenever we change the value of this variable, the JCheckBox reflects this change. This is also true for the opposite direction, so that when we click on the JCheckBox, the variable receives the edited value.

In this same scenario, imagine now that we bind another component to our boolean variable – say – a JToggleButton. Now there are two components that visually display the same value held by that variable. Without surprise, you can realize that whenever the boolean value is changed, both components reflect the new value. Also, if you click either on the JCheckBox or theJToggleButton, the variable and all components bound to it are immediately updated.

This technique is a fundamental step towards the creation of the View and Presentation Model classes in the Presentation Model pattern, where the UI components are kept in the former, and the variables that describe the GUI state, in the latter.

In practice, components that can be bound to a single value are those that display a single value on the screen. This includes: JLabel, JTextField, JTextArea, JCheckBox, JRadioButton,JPasswordField and JFormattedTextField.

To connect these components to a variable, we need an implementation of the ValueModel interface (package com.jgoodies.binding.value), which holds a value and keep it synchronized with the value displayed by the component. Therefore, we can change the value held by theValueModel and the component will reflect this change. In the same way, if the user edits this value through the GUI, the ValueModel will receive the provided value.

public interface ValueModel {
    Object getValue();
    void setValue(Object o);
    void addValueChangeListener(PropertyChangeListener propertyChangeListener);
    void removeValueChangeListener(PropertyChangeListener propertyChangeListener);
}

There are two ways to connect a ValueModel to a UI component. The first one is to use the static method bind() of the Bindings class (package com.jgoodies.binding.adapter):

JTextField textField = new JTextField();
ValueModel valueModel = new ValueHolder();
Bindings.bind(textField, valueModel);

Notice that we create a ValueModel using the ValueHolder class, which is the implementation that we need for this case.

The second possibility is to use a convenient class called BasicComponentFactory (found incom.jgoodies.binding.adapter), which has methods to create the components with the binding idea in mind:

ValueModel valueModel = new ValueHolder();
JTextField textField = new BasicComponentFactory.createTextField(valueModel);

It is important to remember that whenever we bind a UI component to a ValueModel, the former must understand the value held by the latter. Therefore, we can connect without problems aJCheckBox to a ValueModel that holds a Boolean object, but NOT to a ValueModel that holds aDate. If the ValueModel receives a value that cannot be handled by the component, it will throw an Exception.

Case 2 – Binding Components to Lists of Objects

The second type of binding that we can address with the JGoodies API is useful to handle lists of objects that must be displayed on the GUI. In this case the following components can be used:JComboBox, JList and JTable.

The list of objects is represented by the javax.swing.ListModel interface, which provides:

– access to the objects in the list;
– the size of the list;
– capability to observe changes in the list.

public interface ListModel {
    int getSize();
    Object getElementAt(int index);
    void addListDataListener(ListDataListener l);
    void removeListDataListener(ListDataListener l);
}

Since this interface belongs to the Swing platform, the JGoodies’ contribution was two implementations that keep things as simple as the java.util.List interface: ArrayListModel (which inherits from ArrayList and implements ListModel) and LinkedListModel (which inherits fromLinkedList and implements ListModel).

As you can notice, the ListModel interface is not aware of selected objects in the list. This is actually good because in practice there may be lists where only one object can be selected at a time and others where multi-selection is desired. Thus, the ListModel alone does not solve our binding problem.

For lists of objects that can have only one object selected at a time, we can use theSelectionInList class (com.jgoodies.binding.list package). For lists that accept multi-selection, there is no generic class to handle this situation – this will be the subject of another article.

The SelectionInList class is basically a wrapper for a ListModel and a ValueModel. TheValueModel is used here to hold a reference to the selected object in the list. Let’s se how is can be used:

ListModel listModel = new ArrayListModel();
ValueModel selectedItemHolder = new ValueHolder();
SelectionInList selectionInList = new SelectionInList(listModel, selectedItemHolder);

We can bind a SelectionInList object to a JComboBox using an adapter:

JComboBox comboBox = new JComboBox(new ComboBoxAdapter(selectionInList));

We can bind JLists using the same component factory explained before:

JList list = BasicComponentFactory.createList(selectionInList);

The case for JTables is a little bit more complex because we need a TableModel implementation with defined columns.

Here is the source code of an example: https://www.dropbox.com/s/z5e3xouoqzdrawh/JTableBinding.zip?dl=0