The JavaBeans component model relies on a number of rules and conventions bean developers must follow. These conventions are not part of the JavaBeans API itself, but in many ways, they are more important to bean developers than the API itself. The conventions are sometimes referred to as designpatterns ; they specify such things as method names and signatures for property accessor methods defined by a bean.
The reason for these design patterns is interoperability between beans and the beanbox programs that manipulate them. As we've seen, beanbox programs may rely on introspection to determine the list of properties, events, and methods a bean supports. In order for this to work, bean developers must use method names the beanbox can recognize. The JavaBeans framework facilitates this process by establishing naming conventions. One such convention, for example, is that the getter and setter accessor methods for a property should begin with get and set.
Not all the patterns are absolute requirements. If a bean has property accessor methods that do not follow the naming conventions, it is possible to use a PropertyDescriptor object (specified in a BeanInfo class) to indicate the accessor methods for the property. Although the BeanInfo class provides an alternative to the property-accessor-method naming convention, the property accessor method must still follow the conventions that specify the number and type of its parameters and its return value.
A bean itself must adhere to the following conventions:
There are no restrictions on the class name of a bean.
A bean can extend any other class. Beans are often AWT or Swing components, but there are no restrictions.
A bean must provide a no-parameter constructor or a file that contains a serialized instance the beanbox can deserialize for use as a prototype bean, so a beanbox can instantiate the bean. The file that contains the bean should have the same name as the bean, with an extension of .ser.
The name of a bean is the name of the class that implements it or the name of the file that holds the serialized instance of the bean (with the .ser extension removed and directory separator (/) characters converted to dot (.) characters).
A bean defines a property p of type T if it has accessor methods that follow these patterns (if T is boolean, a special form of getter method is allowed):
public T getP()
public boolean isP()
public void setP(T)
Property accessor methods can throw any type of checked or unchecked exceptions
An indexed property is a property of array type that provides accessor methods that get and set the entire array, as well as methods that get and set individual elements of the array. A bean defines an indexed property p of type T if it defines the following accessor methods:
public T getP()
public T getP(int)
public void setP(T)
public void setP(int,T)
Indexed property accessor methods can throw any type of checked or unchecked exceptions. In particular, they should throw an ArrayIndexOutOfBoundsException if the supplied index is out of bounds.
A bound property is one that generates a PropertyChangeEvent when its value changes. Here are the conventions for a bound property:
The getter and setter methods for a bound property follow the same conventions as a regular property.
A beanbox cannot distinguish a bound property from a nonbound property through introspection alone. Therefore, you may want to implement a BeanInfo class that returns a PropertyDescriptor object for the property. The isBound() method of this PropertyDescriptor should return true.
A bean that defines one or more bound properties must define a pair of methods for the registration of listeners that are notified when any bound property value change. The methods must have these signatures:
public void addPropertyChangeListener(PropertyChangeListener) public void removePropertyChangeListener(PropertyChangeListener)
A bean can optionally provide additional methods that allow event listeners to be registered for changes to a single bound property value. These methods are passed the name of a property and have the following signatures:
public void addPropertyChangeListener(String, PropertyChangeListener) public void removePropertyChangeListener(String, PropertyChangeListener)
A bean can optionally provide additional event listener registration methods that are specific to a single property. For a property p, these methods have the following signatures:
public void addPListener(PropertyChangeListener) public void removePListener(PropertyChangeListener)
Methods of this type allow a beanbox to distinguish a bound property from a nonbound property.
When the value of a bound property changes, the bean should update its internal state to reflect the change and then pass a PropertyChangeEvent to the propertyChange() method of every PropertyChangeListener object registered for the bean or the specific bound property.
java.beans.PropertyChangeSupport is a helpful class for implementing bound properties.
A constrained property is one for which any changes can be vetoed by registered listeners. Most constrained properties are also bound properties. Here are the conventions for a constrained property:
The getter method for a constrained property is the same as the getter method for a regular property.
The setter method of a constrained property throws a PropertyVetoException if the property change is vetoed. For a property p of type T, the signature looks like this:
public void setP(T) throws PropertyVetoException
A bean that defines one or more constrained properties must define a pair of methods for the registration of listeners that are notified when any constrained property value changes. The methods must have these signatures:
public void addVetoableChangeListener(VetoableChangeListener) public void removeVetoableChangeListener(VetoableChangeListener)
A bean can optionally provide additional methods that allow event listeners to be registered for changes to a single constrained property value. These methods are passed the name of a property and have the following signatures:
public void addVetoableChangeListener(String, VetoableChangeListener) public void removeVetoableChangeListener(String, VetoableChangeListener)
A bean can optionally provide additional listener registration methods that are specific to a single constrained property. For a property p, these methods have the following signatures:
public void addPListener(VetoableChangeListener) public void removePListener(VetoableChangeListener)
When the setter method of a constrained property is invoked, the bean must generate a PropertyChangeEvent that describes the requested change and pass that event to the vetoableChange() method of every VetoableChangeListener object registered for the bean or the specific constrained property. If any listener vetos the change by throwing a PropertyVetoException, the bean must send out another PropertyChangeEvent to revert the property to its original value, and then it should throw a PropertyVetoException itself. If, on the other hand, the property change is not vetoed, the bean should update its internal state to reflect the change. If the constrained property is also a bound property, the bean should notify PropertyChangeListener objects at this point.
java.beans.VetoableChangeSupport is a helpful class for implementing constrained properties.
In addition to PropertyChangeEvent events generated when bound and constrained properties are changed, a bean can generate other types of events. An event named E should follow these conventions:
The event class should directly or indirectly extend java.util.EventObject and should be named EEvent.
The event must be associated with an event listener interface that extends java.util.EventListener and is named EListener.
The event listener interface can define any number of methods that take a single argument of type EEvent and return void.
The bean must define a pair of methods for registering event listeners that want to be notified when an E event occurs. The methods should have the following signatures:
public void addEListener(EListener) public void removeEListener(EListener)
A unicast event allows only one listener object to be registered at a single time. If E is a unicast event, the listener registration method should have this signature:
public void addEListener(EListener) throws TooManyListenersException
A beanbox can expose the methods of a bean to application designers. The only formal convention is that these methods must be declared public. The following guidelines are also useful, however:
A method can have any name that does not conflict with the property- and event-naming conventions. The name should be as descriptive as possible.
A method can have any number and type of parameters. However, beanbox programs may work best with no-parameter methods or methods that have simple primitive parameters.
A bean can explicitly specify the list of methods it exports by providing a BeanInfo implementation.
A bean can provide user-friendly, human-readable localized names and descriptions for methods through MethodDescriptor objects returned by a BeanInfo implementation.
A bean can provide the following auxiliary classes:
To provide additional information about a bean B, implement the BeanInfo interface in a class named BBeanInfo.
To enable a beanbox to work with properties of type T, implement the PropertyEditor interface in a class named TEditor. The class must have a no-parameter constructor.
To customize the way a beanbox allows the user to enter values for a single property, define a class that implements the PropertyEditor interface and has a no-parameter constructor, and register that class with a PropertyDescriptor object returned by the BeanInfo class for the bean.
To define a customizer, or wizard, for configuring a bean B, define an AWT or Swing component with a no-parameter constructor that does the customization. The class is commonly called BCustomizer, but this is not required. Register the class with the BeanDescriptor object returned by the BeanInfo class for the bean.
Define default documentation for a bean B in HTML 2.0 format and store that documentation in a file named B.html. Define localized translations of the documentation in files by the same name in locale-specific directories.
Beans are distributed in JAR archive files that have the following:
The class or classes that implement a bean should be included in the JAR file, along with auxiliary classes such as BeanInfo and PropertyEditor implementations. If the bean is instantiated from a serialized instance, that instance should be included in the JAR archive with a filename ending in .ser. The JAR file can contain HTML documentation for the bean and should also contain any resource files, such as images, required by the bean and its auxiliary classes. A single JAR file can contain more than one bean.
The manifest of the JAR file must mark any .class and .ser files that define a bean with the attribute:
The manifest of a JAR file can use the Depends-On attribute to specify all other files in the JAR archive on which the bean depends. A beanbox application can use this information when generating applications or repackaging beans. Each bean can have zero or more Depends-On attributes, each of which can list zero or more space-separated filenames. Within a JAR file, / is always used as the directory separator.
The manifest of a JAR file can optionally use the Design-Time-Only attribute to specify auxiliary files, such as BeanInfo implementations, that are used by a beanbox, but not used by applications that use the bean. The beanbox can use this information when repackaging beans for use in an application.
Copyright © 2001 O'Reilly & Associates. All rights reserved.