Binding Beans Blog


    When talking about data binding in Java, people usually think of mapping the contents of XML files to Java objects, as such frameworks have become very popular through the years. However, JAXB or Castor just implement a more general concept. Data binding means wiring attributes or properties of different data structures and optionally keeping them in sync. These can also be JavaBeans.

    This article takes a look at two frameworks for binding beans.JGoodies Binding has been around for several years. It is heavily inspired by thePresentation Model pattern by Martin Fowler. The Java Specification Request 295: Beans Binding and its reference implementation gained widespread recognition in 2007. The JSR is considered for inclusion in Java 7. The article uses both libraries to implement separate versions of a program calledVolumeControl. You can find these examples in the packagescom.thomaskuenneth.articles.binding.beansbinding andcom.thomaskuenneth.articles.binding.jgoodiesbinding. Please consult the Resources section for details. The archive also contains a classic implementation, which can be found incom.thomaskuenneth.articles.binding.classic.

    Installing the Frameworks

    The JGoodies Binding class library is released under the terms of the BSD open source license. It can be downloadedfrom the project home page here at archive contains the sources, a ready-to-use .jar, the documentation, and a tutorial. To get started, unzip the archive and create an empty Java project using your favorite IDE. Add binding-2.0.2.jar andlib\forms-1.2.0b2.jar to the classpath and copy the contents of src\tutorial into the sources folder of your newly created project. You should now be able to launch the demos in com.jgoodies.binding.tutorial and its subpackages. Figure 1 shows the AlbumManagerExample program.

    Figure 1. AlbumManagerExample

    You can build the library on your own, too. The source files are located in src\core and src\extras. The latter contains experimental classes that are not present in the the precompiled archive. Please be sure to putlib\forms-1.2.0b2.jar on the classpath.

    The second framework we are looking at, the reference implementation of JSR 295: Beans Binding, is available for download from its project home page. You can choose from a precompiled archive, the sources, and its Javadoc documentation. I suggest getting the source distribution ( and compiling it on your own. Just create an empty Java project in your favorite IDE and copy the contents of the src folder into the sources directory of your project.

    By now you should have a project for each of the frameworks. As a final step, please create a third project (Examples) and put the contents of there (please consult theResources section for details). Make sure to reference the other projects.

    JavaBeans Revisited

    The JavaBeans specification defines a model for reusable software components. Among many other things, it specifies how components can expose their states and how other objects interested in state changes will get informed when they occur. The underlying idea was to build an application by visually arranging and modifying those beans. Consequently, Swing components, being one of the building blocks of such a program, try to behave as proper beans.

    As we know today, the creation of sophisticated design tools took much longer than originally anticipated. As a result, both the wiring of those of components as well as the creation of application-specific beans had to be done mostly by hand.

    Beans expose their state by means of Getters andSetters. The state is a set of properties. For example, the property backgroundColor can be accessed withgetBackgroundColor() andsetBackgroundColor(). Properties are said to bebound if they can inform interested objects about state changes. Writing such a bean requires:

    • The implementation of all Getters and Setters.
    • Allowing others to be notified of state changes.
    • Firing appropriate events when they occur.

    Establishing a link between beans requires:

    • Implementing appropriate listeners.
    • Registering them with the bean.

    Although the JavaBeans architecture delivers the technical infrastructure for inter-bean communication, there is no immediate built-in support for synchronizing properties. Binding frameworks fill that void.

    The following sections show how to bind a simple application-specific bean calledcom.thomaskuenneth.articles.binding.Volume to three Swing components using either JGoodies Binding or Beans Binding. The archive also contains a traditional implementation, which makes no use of additional frameworks. The three versions of the main program, VolumeControl, reside in different subpackages, so you can compare them easily.

    Representing Properties

    Volume has two bound properties:volume and mute. As you can see in Figure 2, they are manipulated by a checkbox and a slider. A label shows the current value of volume. Additionally,mute controls whether the volume can be adjusted.

    Figure 2. VolumeControl

    The relationship between the involved beans is as follows:

    • The checkbox sets mute.
    • The slider sets volume.
    • mute selects or deselects the checkbox.
    • volume sets the position of the slider.
    • mute enables or disables the slider.
    • volume sets the text of the label.

    com.thomaskuenneth.articles.binding.Volume shows the standard approach of defining bean properties. Bound properties usually fire events through the firePropertyChange()method of PropertyChangeSupport instances. JGoodies Binding has a convenience class,com.jgoodies.binding.beans.Model, which simplifies the task of implementing beans. It already contains much of that boilerplate code.

    Bean properties used to be bound by registeringPropertyChangeListeners and hard-coding their bindings into propertyChange() methods. Both JGoodies Binding and Beans Binding ease that pain by establishing inter-property relationships through simple method calls. Internally, they utilize the JavaBeans infrastructure, but expose bean properties by means of accessor objects.

    Beans Binding introduces the abstract classProperty. It defines a uniform way to access the value of a property. An implementation, BeanProperty, is used to address JavaBeans properties of source objects. For example, Property propertyVolume = BeanProperty.create("volume"); creates an object that can be used to get or set the volume. This is done as follows:

    System.out.println(propertyVolume.getValue(volume)); propertyVolume.setValue(volume, 99); System.out.println(propertyVolume.getValue(volume)); 

    Usually, a Property instance can be used to get and set values of arbitrary beans, which are passed to the corresponding methods. However, there may be subclasses that by themselves store a property value. In this case, they probably ignore the source object.

    JGoodies Binding is based upon thecom.jgoodies.binding.value.ValueModel interface. Such models provide a generic access to a single value, which can be accessed using the getValue() andsetValue() methods. The framework offers several implementations of the interface; for example,ValueHolder and ComponentValueModel. The latter provides bound properties for the JComponentstates enabled and visible, as well as the JTextComponent state editable. You will see shortly how to make use of that.

    ValueHolder, on the other hand, is a simpleValueModel implementation that holds a generic value. If the value changes, a PropertyChangeEvent is fired. Unlike BeanProperty in Beans Binding, it denotes no path to a bean property. You can do this usingcom.jgoodies.binding.beans.PropertyAdapter. This class converts a single bean property into the genericValueModel interface. BeanAdapter can do that with multiple properties of the same bean.

    Property (Beans Binding) andValueModel (JGoodies Binding) provide means for reading and writing values. They can also inform registered listeners about value changes. Finally, as you will see in the following section, both are used to establish bindings.

    Establishing Bindings

    In Beans Binding, the abstract classorg.jdesktop.beansbinding.Binding represents the concept of a binding between two properties. The class contains methods for syncing them upon explicit requests. Automatic updates, according to some specified strategy, are implemented by subclasses. Bindings can be obtained from the factory class org.jdesktop.beansbinding.Bindings.

    For example, AutoBinding syncs its source and target objects according to one of the following update strategies:

    • AutoBinding.UpdateStrategy.READ_ONCE
    • AutoBinding.UpdateStrategy.READ
    • AutoBinding.UpdateStrategy.READ_WRITE

    Connecting the volume bean property to a slider is achieved by:

    Property propertyVolume = BeanProperty.create("volume"); Property propertySliderValue = BeanProperty.create("value"); Binding bindingVolumeSlider = Bindings.createAutoBinding( AutoBinding.UpdateStrategy.READ_WRITE, volume, propertyVolume, sliderVolume, propertySliderValue); bindingVolumeSlider.bind(); 

    The bean property volume is an instance ofcom.thomaskuenneth.articles.binding.Volume, whereassliderVolume is a JSlider. Moving the slider updates the bean, and invoking setVolume()changes the slider location, because the update strategy is set toUpdateStrategy.READ_WRITE. VolumeControlcontains a label that prints the current value of the bean propertyvolume. If the update strategy of that binding was set to READ_WRITE as well, invokinglabelInfo.setText() would change the property. This is not intended, so the binding is created as follows:

    Property propertyVolume = BeanProperty.create("volume"); Property propertyLabel = BeanProperty.create("text"); Binding bindingVolumeLabel = Bindings.createAutoBinding(AutoBinding.UpdateStrategy.READ, volume, propertyVolume, labelInfo, propertyLabel); 

    This way the target (the label) is kept in sync with the source, but not vice versa.

    JGoodies Binding works in a similar fashion. It offers two helper classes for establishing a binds components that have been created before. It wraps ValueModels with the adapters from the packagecom.jgoodies.binding.adapter. This approach is showcased incom.thomaskuenneth.articles.binding.jgoodiesbinding.VolmeControl. Alternatively, you can usecom.jgoodies.binding.adapter.BasicComponentFactory. This class creates Swing components that are then bound using theBindings class. The sample VolumeControl2shows you how to do that.

    To bind an already-created checkbox to the bean propertymute you have to:

    PropertyAdapter<Volume> adapterMute = new PropertyAdapter<Volume>(volume, "mute", true); Bindings.bind(checkboxMute, adapterMute); 

    Invoking checkboxMute.setSelected() will modify themute bean property and vice versa. Bindingvolume to a label is almost as easy. The following example also shows you how to convert between different formats. You will see shortly why this may be necessary.

    PropertyAdapter<Volume> adapterVolume = new PropertyAdapter<Volume>(volume, "volume", true); ValueModel labelModel = ConverterFactory.createStringConverter(adapterVolume, NumberFormat.getIntegerInstance()); Bindings.bind(labelInfo, labelModel); 

    The label is bound to a ValueModel, which has been derived from the original PropertyAdapter by invokingConverterFactory.createStringConverter(). It convertsIntegers to Strings. This is necessary to avoid PropertyAccessExceptions, which would occur because the data types of the source and target beans are different.

    Beans Binding knows converters, too. Once a binding is created, you can invoke setConverter().

    Property propertyMute = BeanProperty.create("mute"); Property propertySliderEnabled = BeanProperty.create("enabled"); Binding bindingMuteSlider = Bindings.createAutoBinding( AutoBinding.UpdateStrategy.READ, volume, propertyMute, sliderVolume, propertySliderEnabled); bindingMuteSlider.setConverter(new Converter() { @Override public Object convertForward(Object value) { return !((Boolean) value); } @Override public Object convertReverse(Object value) { return convertForward(value); } }); bindingMuteSlider.bind(); 

    In this example, the bean property mute is bound to the enabled state of a slider. As the slider should be movable only if mute is false, its state needs to be negated before it is passed to the component. Converter classes extend org.jdesktop.beansbinding.Converter and override its methods convertForward() andconvertReverse().

    To achieve the same using JGoodies Binding, you can usecom.jgoodies.binding.beans.PropertyConnector to keep two bean properties in sync. The framework also offers a converter that can negate Booleans. Here is how you can wire things up:

    PropertyAdapter<Volume> adapterMute = new PropertyAdapter<Volume>(volume, "mute", true); ValueModel negator = ConverterFactory.createBooleanNegator(adapterMute); PropertyConnector connector = PropertyConnector.connect(negator, "value", sliderVolume, "enabled"); 

    The idea is to connect the slider to a converter, which in turn gets its data from a PropertyAdapter.

    Structuring Applications

    All versions of VolumeControl have a very similar structure. In particular, the JGoodies Binding and Beans Binding implementations resemble each other closely, besides, of course, the actual binding activities in initEventHandling(). Still, they intentionally share the same weakness: enabling or disabling the slider is woven into the binding process.

    The Presentation Model pattern by Martin Fowler transfers the state and behavior of a view to a model class, which communicates both with the domain layer and the view. JGoodies Binding nicely incorporates this pattern. It provides an implementation,com.jgoodies.binding.PresentationModel, that can be used either directly or as a subclass (as incom.thomaskuenneth.articles.binding.jgoodiesbinding.VolumeControlPresentationModel). My implementation contains the code for enabling or disabling the slider. It utilizes ComponentValueModel, which adds several component states to ValueModels. This is done as follows:

    getComponentModel(Volume.PROPERTY_VOLUME).setEnabled( !getModel(Volume.PROPERTY_MUTE).booleanValue()); 


    Both JGoodies Binding and Beans Binding are powerful frameworks that significantly ease the development of Swing applications. The incorporation of the Presentation Model pattern helps structuring a program, making it more readable and maintainable. Having been in the market for quite a while now, JGoodies Binding has become very mature. Still, Beans Binding makes binding beans a breeze, too. In the long run, it might become the framework of choice, especially if it is included in a future Java version and an application must rely exclusively on core libraries.