This article is sponsored by the Java Community Process.
Frank Sommers: What problem does the Data Binding API solve?
Shannon Hickey: Data binding is about making connections between beans or objects, and about syncing up properties of two different objects.
Data binding is particularly interesting with Swing components, where you have application objects, and you want to bind them to user interface components. That way, the UI components can display the values of those application objects. Further, you can use the UI components to allow the user to set the values of the application objects.
Before the Beans Binding framework, a lot of boilerplate code
had to be written to listen for changes of one property of an
object, set a value of another object's property, and vice versa.
The initial goal of Beans Binding is to simplify making
connections between such properties and objects. There is an
additional emphasis on Swing components, and especially on
binding to complex Swing components, such as a
Frank Sommers: What are the special technical challenges in the use-cases you mentioned? Couldn't you just use the JavaBeans properties and listener patterns to notify one object of changes in another object?
Shannon Hickey: You certainly can. For the
simple case of connecting two properties of JavaBeans, you can
write code to add a
PropertyChangeListener to the
first JavaBean, listen for changes, and then set the value on the
second bean, and vice versa. You can use those two listeners to
propagate the changes back and forth. That's simple with
JavaBeans, although it's a lot easier with Beans Binding, where
you can create an object with a strategy that dictates how the
beans should sync up.
This gets more complex with some Swing components that don't
behave as proper beans. For example, the
DocumentChangeEvents when the value of the text
changes. In that case, you need to add a
DocumentListener to the document of a
TextComponent to listen for changes. Likewise,
need to remember all that boilerplate code when interacting with
different components to figure out how you can connect them.
Even more complex is the case with something like
JTable when you work with the
Collections classes. Let's say you have a
Items. You would have to create
a custom model to set on your target component, and propagate the
changes from the
List to that model. With Beans
Binding, you can create a binding between the
JTable or a
JList, and have the
List behind the scenes automatically create the
model and listen for changes to display in the table.
Frank Sommers: How does Beans Binding reduce the boilerplate code developers have to write when connecting bean properties?
Shannon Hickey: Beans Binding raises the abstraction level for connecting bean properties.
The first thing we've done is create an abstract
Property class that represents a way to get at a
property on some source object. Beans Binding provides two
Property: One is
BeanProperty, which uses a simple property path
syntax to indicate which property is being referenced. With this
simple syntax, if you have a
Person object with a
mother property, and you wanted to create a
Property that refers to the
firstName, you could create a
The other way to specify properties is via more complex
expressions of a property, using the Java EL expression language.
For that latter use-case, we define an
As a result of that higher level of abstraction, there is a
lot less boilerplate code for you to write. Suppose you want to
bind the selected item of a
JList to the text of a
TextField. With Beans Binding, you would create a
Property that describes the selected item, and
Property that represents the text in a
JTextField. Then you would just create the binding
between those two
Property objects. There is no more
figuring out what type of listener needs to be added to the
JList, or what type of listener needs to be added to
TextComponent. You're using a common pattern,
regardless of that you're binding.
In addition to raising the level of abstraction for your code,
Beans Binding does more: It allows you to traverse paths along
properties, and reference multiple methods on those paths. For
instance, you can create a
the first name of a person's mother. That
in effect, represents the call to
getMother().getFirstName(). And that
Property also listens to property changes along the
path and updates its value any time any of the objects in the
path change. If the person's mother property changes, or the
mother's first name changes, the first name property value will
automatically be updated.
In addition, the
Person itself may be referenced
from another bean. In that case, even changing the
Person would update the property. For example, you
may have a map of some keys to
Person objects. When
the value of
Person in the map changes, Beans
Binding will update the mother's first name property in response
to that change.
Once you start dealing with more complex paths, there's a lot
more boiler plate code you would have to write without Beans
Binding. Consider this example: You want to bind a
JTable to a list of
Person objects. In
addition, you also want to bind some other object to the table's
selected item: For example, you want to show the selected
person's mother's first name in a
Any time the selected item in the table changes, you want that first name field's text to update. But you also want to update that first name field if the person's mother's first name is changed in the list. You would have to write a lot of error-prone, repetitious code that Beans Binding simplifies for you.
Frank Sommers: You described how
away the complexity of adding listeners to a bean. How do you
wire up these properties for notifications with Beans
Shannon Hickey: Suppose you want to bind the
firstName property to a
text field. You start by creating the
object: invoke the
BeanProperty.create() method with
the string "firstName" to create the first bean property.
Similarly, create a bean property called "text" that represents
text property of the
Then, you create an auto-binding with
Bindings.createAutoBindings(), passing that method
four parameters: the first bean (the person), the "firstName"
property, which says that you want to apply that property to the
Person object, then the
then the "text" property.
When creating an auto-binding, you also must pass in the update strategy. An auto-binding has three update strategies: read once, read, and read-write. The first strategy means that the property is read only when the binding is made. With read, any time the first property changes, the binding will refresh the target from the source. And read-write applies the changes in both directions.
Frank Sommers: What are the requirements for a bean to participate in this process?
Shannon Hickey: The
ELProperty, which are our implementations,
require JavaBeans: the properties these bindings represent are
For a property to be readable, the property requires a
is()set() method as well. If
there are not going to be any changes to the bean, then that's
enough, such as when you just want to display the value of
something in a label without the source ever changing.
Once you start dealing with bindings whose source is going to
change, you need to fire property change notifications in order
to have them work properly with
ELProperty. This follows the common pattern of
writing a bean: a bean needs to maintain a list of property
change listeners, and notify those listeners with the correct
property names and values. I believe the Swing Application
Framework [JSR 296] may even provide an abstract bean you can
build on that follows all these patterns.
ELProperty work with a
Map, in that
they can use the property name as the key into a map. If you map
the string "key" to some value, fetching the bean property with
that string represents calling
get() with that
string on that map. In order to respond to changes in the map,
the map has to be an instance of
provided by this project. We have convenience methods that take a
map and wrap it into observable map.
There is also a third set of things that we nicely and quietly
deal with. As I mentioned, many of the Swing components are not
proper JavaBeans, or do not have proper JavaBean properties with
respect to some of the interesting things you'd want to listen
to. For example,
JSlider doesn't provide a
value property, a
text property, and
doesn't have a
selectedElement property. Those are
situations where you need to know all the boiler plate code to
write in order to listen for changes.
To address that issue, in BeansBinding we provide the ability to register synthetic properties. A synthetic property creates a drop-in replacement for a bean to be used in Beans Binding.
JTable.selectedElement is an example of this.
JTable doesn't have a
selectedElement property, we provide a behind the
scenes a drop-in, which is a bean that provides a
selectedElement method, listens to
JTable changes, and updates what it considers to be
selectedElement in response to those
changes. That allows developers to just bind
selectedElement like they would any other proper
The way we support these synthetic properties is via a
registry of what we call adapters. We hope to eventually open
this registry up so that third parties can provide adapters for
their beans. We currently provide synthetic properties for the
interesting Swing components. In addition to
JTable.selectedElement, we also provide
value: all these things should
be proper JavaBean properties, but aren't. We could fix these in
future versions of Swing, but Beans Binding is designed to work
with Java 5.0 and forward.
Frank Sommers: Swing's single event threading rule states that you are only supposed to change the state of a Swing component in the event handling thread. When you update the property of a visual bean, such as a Swing component, does the Beans Binding API take into account the Swing event handling thread?
Shannon Hickey: No, everything occurs on the thread in which the event is called. You can use one of the existing patterns and tools that are available to address that. If you're getting an object from the network, and you want to change the binding, then you need to change that binding on the event handler thread.
Frank Sommers: The Beans Binding API has been in development for a while now. How has the API changed over time? What sort of feedback from the expert group and users benefited the API the most?
Shannon Hickey: JSR 295 was initiated by Scott Violet before he left Sun, and I inherited it form him. The implementation of the API changed quite significantly with respect to the design goals that Scott had set out.
In the initial version, EL was a requirement. A binding was
created with four parameters: source and target object, and two
strings. The first string was interpreted as EL all the time, and
the second one was interpreted as a simple path. A lot of the
expert group and the community didn't want to have to deal with
EL. With this community, we decided to create this abstract
Property class so people can use
BeanProperty or, if they wanted to, ELProperty.
Users can even create their implementations of
Property. So the API is no longer hard-coded to EL.
That was a big win, and it got a lot people happy and interested
in the project.
The second major change was about ad-hoc parameters for
configuring special bindings. For example, when binding to a
JTable, you want the table to display properties of
some elements in different columns. In the old implementation,
doing this was confusing, and there was no type safety. The
second major re-architecture for 1.0 was to create binding
subclasses for these complex cases. There is a
JComboBox binding, and
JList binding. In the
there are methods for adding column binding, and column bindings
have methods on them for setting whether or not they're editable
and what class they represent.
Frank Sommers: There are currently several proposals to add native property support to the Java language. To what extent would language-level properties make data binding an easier task?
Shannon Hickey: There has been a lot of confusion about Beans Binding and its relation to proper property support in the language. Some people are afraid that Beans Binding will somehow stall adding property support for the language.
Any effort about adding property support to the language is happening separately from Beans Binding. The Beans Binding API is designed to work with Java 5.0, and with old JavaBeans, and to solve an existing problem.
Had actual property support been in the language, it would
have made some of the architecture in Beans Binding different
than what it is now. My goal with the Beans Binding project is to
ensure that if, and when, property support is added to the
language, it's easy to create an adapter or custom property type
in Beans Binding. We designed the abstract
class such that when proper language support is added, we could
provide an additional implementation that uses native
Frank Sommers: There are several other projects in the Java community that aim to address the problem of binding JavaBeans properties. How does the JSR 295 API relate to those projects?
Shannon Hickey: As I mentioned, I inherited the JSR 295 API from Scott Violet, and Scott had evaluated related projects in the community at the time JSR 295 commenced. So I cannot speak what specific projects and APIs influenced the initial design of the Beans Binding API.
Currently, the Beans Binding API and the related java.net project work closely with several other community initiatives, especially in the Swing community. Perhaps the most significant example of a project using the JSR 295 API is NetBeans 6, which already has support for the Beans Binding project in its GUI builder.
In NetBeans 6's UI designer, dragging a database table bean onto a form will automatically create bindings between some database object and Swing components. NetBeans also provides form editors for creating bindings. Since NetBeans 6 also supports the Swing Application Framework API [JSR 296], it is possible to rapidly create a UI that relies on the Swing App Framework as well as uses the Beans Binding framework.
The Beans Binding project also makes use of several other
projects from the Java community. The EL expression language we
use in specifying
ELProperty objects is from the
GlassFish project, with some minor changes that we needed for
Beans Binding. Hopefully, we can get those changes back into the
official EL version in the future.
Frank Sommers: How stable is the Beans Binding API now? What are your future plans for JSR 295?
Shannon Hickey: The JSR is ongoing, and the end goal is to have it be a part of Java 7. The reference implementation is being developed in the open on java.net. I've been releasing builds when I think the project code is stable, and that has allowed people to provide feedback and to start using it even now. It is being used now quite widely, and the feedback from the community has really been invaluable.
Frank Sommers is a Senior Editor with Artima Developer. He also serves as chief editor of the IEEE Technical Committee on Scalable Computing's newsletter, and is an elected member of the Jini Community's Technical Advisory Committee. Prior to joining Artima, Frank wrote the Jiniology and Web services columns for JavaWorld.
This article is sponsored by the Java Community Process.