Skip to main content

The Unknown JavaBean

Posted by rbair on May 31, 2006 at 6:19 PM PDT

What is a JavaBean? What is the JavaBean design pattern? If I asked that question in a room of a hundred people, I suspect fewer than 10 would really get it right.

For the majority of Java developers, the JavaBean pattern is simply a naming convention for accessors/mutators (getters/setters) for a property. For example:

  public class Supplier {
    private String name;
   
    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }
  }

This example highlights the predominate usage of a "JavaBean". There is a property called "name". By convention, the accessor method is "get[Name of Property]" and the mutator method is "set[Name of Property]". If the property happens to be a boolean, the accessor could also be named "is[Name of Property]". For example, "isEnabled()". The other thing that most people get right is that a JavaBean has a default constructor. Why JFreeChart's ChartPanel doesn't have a default constructor is beyond me, and actually the irritation that caused this blog. I just wanna put a chart into my Matisse form. Is that too much to ask?

In any case, accessors and mutators are all well and good, but this doesn't make our class a JavaBean. Well, not a real JavaBean. JavaBeans are intended to be the component model for Java. You know, the equivilent of all those fancy components you can use in the .NET world. The idea being that there would be some standard component model, and then a component market would sprout up so that developers just go into the marketplace, pay a few hundred dollars for the charting component library they need, and wire it all together in the IDE. This approach has worked for other development environments (Visual Basic being the predominant example, Delphi being another), but has never been quite the same for the Java market.

I'm sure there are reasons for that, and I could write a very long blog on the subject and stir, I'm sure, some controversy in the process, but that isn't the point here. First, let's all get on the same page as to what a JavaBean really is.

A JavaBean does much more than provide accessor/mutator methods for internal state that follows some naming convention. To be properly understood, you have to think of things in terms of components. Internal state is internal state and should never be exposed in the API. What is exposed is that state that can be fiddled with. You know, background color, name, address, preference factory... that sort of stuff. Think of the bean as a black box, reveal those switches and properties to the outside world that they should be aware of. Whatever happens inside the box, stays inside the box.

JavaBeans are also observable. When one of the public properties of the bean changes, notification has to be sent so that everybody knows that the bean has had a property change. In the JavaBeans world, these are PropertyChange events. Every real JavaBean allows you to register PropertyChangeListeners with the bean, and observe PropertyChangeEvents as they occur. This is a critical component to using a real component model -- and very handy for utility applications as well (such as databinding systems).

The standard way to support these property change events is to use PropertyChangeSupport, which is a class in the java.beans package. This is normally the kind of code you'd write to do this:

  public class MyBean {
    /**
     * Helper class that manages all the property change notification machinery.
     * PropertyChangeSupport can not be extended directly because it requires
     * a bean in the constructor, and the "this" argument is not valid until
     * after super construction. Hence, delegation instead of extension
     */
    private PropertyChangeSupport pcs;
   
    /** Creates a new instance of MyBean */
    public MyBean() {
      pcs = new PropertyChangeSupport(this);
    }
    /**
     * This method shows what all the methods really do -- delegate to
     * the PropertyChangeSupport. The other methods have been trimmed for
     * space efficiency. This is just a blog, after all
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
      pcs.addPropertyChangeListener(listener);
    }
    public void removePropertyChangeListener(PropertyChangeListener listener) {...}
    public PropertyChangeListener[] getPropertyChangeListeners() {...}
    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {...}
    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {...}
    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {...}
    public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {...}
    public void firePropertyChange(String propertyName, int oldValue, int newValue) {...}
    public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {...}
    public void firePropertyChange(PropertyChangeEvent evt) {...}
    public void fireIndexedPropertyChange(String propertyName, int index,
  Object oldValue, Object newValue) {...}
    public void fireIndexedPropertyChange(String propertyName, int index,
  int oldValue, int newValue) {...}
    public void fireIndexedPropertyChange(String propertyName, int index,
  boolean oldValue, boolean newValue) {...}
    public boolean hasListeners(String propertyName) {...}
}

Kind of a pain, huh? Fortunately, if you are writing a visual component, all this nonsense is handled for you in java.awt.Component. All you have to do is remember to fire the property change notification in your setter method. Like so:

  public void setFoo(String newFoo) {
    String old = getFoo();
    this.foo = newFoo;
    firePropertyChange("foo", old, getFoo());
  }

Ok, that's a lot better. But JavaBeans and PropertyChange notification is very important for the nonvisual component as well as the visual component. Why do you want nonvisual components? .NET has a useful one: Timer. Its a simple component with a few properties like "delay", and a single event that is fired when the timer has expired. This means that in your GUI builder of choice, you simply pick the "Timer" component from the palette, add it to the form, change the properties in the property sheet, fill out an event handler (all through the GUI builder, mind you) and you're done. All you hand-gui-code-gurus out there are probably laughing right now, but I'm not talking to you. I'll try to convince you of the error of your hand-gui-coding ways some other time.

To ease development of non visual JavaBean components, there is a base class in the SwingX project that simplifies this problem called JavaBean. It makes it as trivial to fire event notification and write a true JavaBean as it is for a subclass of Component. The only hitch is, you have to extend JavaBean. That shouldn't be that big a deal. Take your most root objects (those that extend Object) and instead extend JavaBean. Done.

So what does this look like? Well, taking our original example:

  public class Supplier extends JavaBean {
    private String name;
   
    public String getName() {
      return name;
    }

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

Bam. Two lines of new code, and bingo. I've got a real JavaBean. And this class is really valuable for a lot more than just GUI builders. There are several really interesting frameworks that could use this class and others like it, such as databinding. I'll leave other framework examples as an exercise to the reader. Hint: check the slides for the Data Access Strategies talk from this past JavaOne.

There is a lot more that can go into writing a full fledged JavaBean, such as BeanInfo's, EventSetDescriptors, and the like. But this is enough for one blog. Now, back to trying to make ChartPanel a friggin' JavaBean...