Chapter 6. JavaBeans
The JavaBeans API provides a framework for defining reusable, embeddable, 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 (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 Java Enterprise in a Nutshell (O'Reilly)) 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.
One of the goals of the JavaBeans model is interoperability with similar component frameworks. So, for example, a native Windows program can, with an appropriate bridge or wrapper object, use a JavaBeans component as if it were a COM or ActiveX component. The details of this sort of interoperability are beyond the scope of this chapter, however.
The JavaBeans component model consists of the java.beans and java.beans.beancontext packages and a number of important naming and API conventions to which conforming beans and bean-manipulation tools must adhere. Because JavaBeans is a framework for generic components, the JavaBeans conventions are, in many ways, more important than the actual API.
Two interesting technologies related to JavaBeans are the Java Activation Framework and InfoBus. Both are standard extensions, implemented in the javax.activation and javax.infobus packages, respectively. You can read more about them at the JavaBeans web site: http://java.sun.com/beans/.
Beans can be used at three levels by three different categories of programmers:
6.1. Bean Basics
Any object that conforms to certain basic rules can be a bean; there is no Bean class all beans are required to subclass. Many beans are AWT components, but it is also quite possible, and often useful, to write "invisible" beans that do not have an onscreen appearance. ( Just because a bean does not have an 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 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 and with other beans by generating events. The JavaBeans API uses the same event model AWT and Swing components use. This 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 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 proper ty 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.
Because Java allows dynamic loading of classes, beanbox programs can load arbitrary beans. The beanbox tool uses a process called introspection to determine the properties, events, and methods exported by a bean. The introspection mechanism is implemented by the java.beans.Introspector class; it relies on both the java.lang.reflect reflection mechanism and a number of JavaBeans naming conventions. Introspector can determine the list of properties supported by a bean, for example, by scanning the class for methods that have the right names and signatures to be get and set property accessor methods.
The introspection mechanism does not rely on the reflection capabilities of Java alone, however. Any bean can define an auxiliary BeanInfo class that provides additional information about the bean and its properties, events, and methods. The Introspector automatically attempts to locate and load the BeanInfo class of a bean.
The BeanInfo class provides additional information about the bean primarily in the form of FeatureDescriptor objects, each one describing a single feature of the bean. Each FeatureDescriptor provides a name and brief description of the feature it documents. The beanbox tool can display the name and description to the user, making the bean essentially self-documenting and easier to use. Specific bean features, such as properties, events, and methods, are described by specific subclasses of FeatureDescriptor, such as PropertyDescriptor, EventSetDescriptor, and MethodDescriptor.
One of the primary tasks of a beanbox application is to allow the user to customize a bean by setting property values. A beanbox defines property editors for commonly used property types, such as numbers, strings, fonts, and colors. If a bean has a property of a more complicated type, however, it can define a PropertyEditor class that enables the beanbox to let the user set values for that property.
In addition, a complex bean may not be satisfied with the property-by-property customization mechanism provided by most beanbox tools. Such a bean can define a Customizer class to create a graphical interface that allows the user to configure a bean in some useful way. A particularly complex bean can even define customizers that serve as "wizards" that guide the user step by step through the customization process.
A bean context is a logical container (and often a visual container) for JavaBeans and, optionally, for other nested bean contexts. In practice, most JavaBeans are AWT or Swing components or containers. Beanbox tools recognize this and allow component beans to be nested within container beans. A bean context is a kind of heavyweight container that formalizes this nesting relationship. More importantly, however, a bean context can provide a set of services (e.g., printing services, debugging services, database connection services) to the beans it contains. Beans that are aware of their context can be written to query the context and take advantage of the services that are available. Bean contexts are implemented using the java.beans.beancontext API, which is new as of Java 1.2 and discussed in more detail later in this chapter.
Copyright © 2001 O'Reilly & Associates. All rights reserved.