7.4. JavaBeans Conventions
JavaBeans is a framework for
defining reusable modular software components. The JavaBeans
specification includes the following definition of a bean:
"a reusable software component that can be
manipulated visually in a builder tool." As you can
see, this is a rather loose definition; beans can take a variety of
forms. The most common use of beans is for graphical user interface
components, such as components of the java.awt and
javax.swing packages, which are documented in
Java Foundation Classes in a Nutshell and
Java Swing, both from O'Reilly.
Although all beans can be manipulated visually, this does not mean
every bean has its own visual representation. For example, the
javax.sql.RowSet class (documented in
O'Reilly's Java
Enterprise in a Nutshell) is a JavaBeans component that
represents the data resulting from a database query. There are no
limits on the simplicity or complexity of a JavaBeans component. The
simplest beans are typically basic graphical interface components,
such as a java.awt.Button object. But even complex
systems, such as an embeddable spreadsheet application, can function
as individual beans.
The JavaBeans component model consists of the
java.beans, the
java.beans.beancontext packages, and a number of
important naming and API conventions to which conforming beans and
bean-manipulation tools must adhere. These conventions are not part
of the JavaBeans API itself but are in many ways more important to
bean developers than the API itself. The conventions are sometimes
referred to as design
patterns; they specify such things as method
names and signatures for property accessor methods defined by a bean.
If the class you are writing is not intended to be a bean, suitable
for visual manipulation in a builder tool, you don't
need to follow these conventions. The JavaBeans conventions are
widely used and well-understood, however, and you can improve the
usability and reusabilty of your code by following the relevant ones.
This is particularly true of the property accessor method naming
conventions.
We cover the conventions themselves later in this section. First,
however, an overview of the JavaBeans model is in order.
7.4.1. Bean Basics
Any object that conforms to certain
basic rules can be a bean; there is no Bean class
that all beans are required to subclass. Many beans are GUI
components, but it is also quite possible, and often useful, to write
"invisible" beans that do not have
an onscreen appearance. (A bean having no onscreen appearance in a
finished application does not mean it cannot be visually manipulated
by a beanbox tool, however.)
A
bean is characterized by the properties, events, and methods it
exports. It is these properties, events, and methods that an
application designer manipulates in a beanbox tool. A
property
is a piece of the bean's internal state that can be
programmatically set and/or queried, usually through a standard pair
of get and set accessor
methods.
A bean communicates with the
application in which it is embedded as well as with other beans by
generating events. The JavaBeans API uses the
same event model that AWT and Swing components use. The model is
based on the java.util.EventObject
class and
the java.util.EventListener interface; it is
described in detail in Java Foundation Classes in a
Nutshell (O'Reilly). In brief, the event
model works like this:
A bean defines an event if
it provides add and remove
methods for registering and deregistering listener objects for that
event. An application that wants to be notified when an event of that type
occurs uses these methods to register an event listener object of the
appropriate type. When the event occurs, the bean notifies all registered listeners by
passing an event object that describes the event to a method defined
by the event listener interface.
A
unicast event is a rare kind of event for which
there can be only a single registered listener object. The
add registration method for a unicast event throws
a TooManyListenersException if an attempt is made
to register more than a single listener.
The
methods exported by a bean are simply any public
methods defined by the bean, excluding those methods that get and set
property values and register and remove event listeners.
In addition to the regular sort of
properties described earlier, the JavaBeans API also supports several
specialized property subtypes. An indexed
property is a property that has an array value, as well as
getter and setter methods that access both individual elements of the
array and the entire array. A bound property is
one that sends a PropertyChangeEvent to any
interested PropertyChangeListener objects whenever
the value of the property changes. A constrained
property is one that can have any changes vetoed by any
interested listener. When the value of a constrained property of a
bean changes, the bean must send out a
PropertyChangeEvent to the list of interested
VetoableChangeListener objects. If any of these
objects throws a PropertyVetoException, the
property value is not changed, and the
PropertyVetoException is propagated back to the
property setter method.
7.4.2. Bean Classes
A bean class itself must adhere to
the following conventions:
- Class name
-
There are no restrictions on the class name of a bean.
- Superclass
-
A bean can extend any other class. Beans are often AWT or Swing
components, but there are no restrictions.
- Instantiation
-
A bean should provide a no-parameter constructor so bean manipulation
tools can easily instantiate the bean.
7.4.3. Properties
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):
- Getter
-
public T
getP(
)
- Boolean getter
-
public boolean
isP( )
- Setter
-
public void
setP(T)
- Exceptions
-
Property accessor methods can
throw any type of checked or unchecked exceptions.
7.4.4. Indexed Properties
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:
- Array getter
-
public T[ ]
getP()
- Element getter
-
public T
getP(int)
- Array setter
-
public void
setP(T[])
- Element setter
-
public void
setP(int,T)
- Exceptions
-
Indexed
property accessor methods can throw any type of checked or unchecked
exceptions. They should throw an
ArrayIndexOutOfBoundsException if the supplied
index is out of bounds.
7.4.5. Bound Properties
A bound property is one that
generates a PropertyChangeEvent when its value
changes. Here are the conventions for a bound property:
- Accessor methods
-
The getter and setter methods for a bound property follow the same
conventions as a regular property.
- Listener registration
-
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 changes.
The methods must have these signatures:
public void addPropertyChangeListener(PropertyChangeListener)
public void removePropertyChangeListener(PropertyChangeListener)
- Named property listener registration
-
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)
- Per-property listener registration
-
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 an unbound property.
- Notification
-
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.
- Support
-
java.beans.PropertyChangeSupport
is a helpful class for implementing bound properties.
7.4.6. Constrained 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:
- Getter
-
The getter method for a constrained property is the same as the
getter method for a regular property.
- Setter
-
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
- Listener registration
-
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)
- Named property listener registration
-
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)
- Per-property listener registration
-
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)
- Notification
-
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 vetoes the change by throwing a
PropertyVetoException, the bean must send out
another PropertyChangeEvent to revert the property
to its original value. It should then 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.
- Support
-
java.beans.VetoableChangeSupport
is a helpful class for implementing constrained properties.
7.4.7. Events
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:
- Event class
-
The event class should directly or
indirectly extend java.util.EventObject and should
be named EEvent.
- Listener interface
-
The event must be associated with an
event listener interface that extends
java.util.EventListener and is named
EListener.
- Listener methods
-
The event listener interface can
define any number of methods that take a single argument of type
EEvent and return
void.
- Listener registration
-
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)
- Unicast events
-
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
|