TOC
BACK
FORWARD
HOME

Java 1.1 Unleashed

- 39 -
The JavaBeans API

by Michael Morrison

IN THIS CHAPTER

  • Property Management
  • Introspection
  • Event Handling
  • Persistence
  • Application Builder Support


With all the neat things JavaBeans accomplishes, you might imagine that there is some highly complex system pulling all kinds of magical tricks under the hood. The truth is, there is no magic behind JavaBeans and surprisingly little complexity considering how advanced it is as a software component technology. The lack of complexity in JavaBeans is because of the well-designed JavaBeans API, which is completely responsible for carrying out all the interesting ideas you learned about in the previous chapter.

In this chapter, you take a quick tour through the JavaBeans API to familiarize yourself with all emergency locations <grin>. Actually, the tour is meant to help you get the big picture of how the API is divided and what type of functionality each part of it addresses. Although there are a decent number of classes and interfaces defined in the API, you don't have to worry about them just yet. Being faced with a large amount of new information to process and digest is always somewhat overwhelming, so this chapter hits just the high points. This way, you'll have some perspective when you dig into more details in the next couple of chapters.

In this chapter, keep in mind that JavaBeans is ultimately a programming interface, which means that all its features are implemented in the java.beans package. The java.beans package is also referred to as the JavaBeans API and is provided as part of the standard Java 1.1 class library. The JavaBeans API itself is merely a suite of smaller APIs devoted to specific functions, or services. Following is a list of the main component services in the JavaBeans API that are necessary to facilitate all the features that make JavaBeans such an exciting technology:

  • Property management

  • Introspection

  • Event handling

  • Persistence

  • Application builder support

By understanding these services and how they work, you'll have much more insight into exactly what type of technology JavaBeans is. This entire chapter is devoted to helping you understand the basics of these APIs and why they are necessary elements of the JavaBeans architecture.

Property Management

The property management facilities in the JavaBeans API are responsible for handling all interactions relating to bean properties. Properties reflect the internal state of a bean and constitute the data part of a bean's structure (remember that beans have two basic parts: a data part and a method part). More specifically, properties are discrete, named attributes of a bean that determine its appearance and behavior. Properties are important in any component technology because they isolate component state information into discrete pieces that can be easily modified.

To help you get a better idea of the importance of properties, consider some different scenarios that deal with properties. Following are some examples of how bean properties are accessed and used:

  • As object fields in scripting environments such as JavaScript or VBScript

  • Programmatically, using public accessor methods

  • Visually, using property sheets in application builder tools

  • Through the persistent storage and retrieval of a bean

As this list shows, properties come into play in a variety of ways when it comes to bean access and manipulation. Notice the flexibility properties provide: You can access them through scripting languages such as JavaScript, through full-blown programming languages such as Java, and through visual builder tools. This freedom to access and manipulate beans in a variety of ways is one of the critical design goals of the JavaBeans technology. And it is fulfilled by the property management facilities in the JavaBeans API. The next few sections discuss some of the major issues addressed by the JavaBeans API property management facilities.

Accessor Methods

The primary way properties are exposed in the JavaBeans API is through accessor methods. An accessor method is a public method defined in a bean that directly reads or writes the value of a particular property. Each property in a bean must have a corresponding pair of accessor methods: one for reading the property and one for writing. The accessor methods responsible for reading are known as getter methods because they get the value of a property. Likewise, accessor methods responsible for writing are known as setter methods because they set the value of a property.

Indexed Properties

So far, the discussion of properties has been limited to single-value properties, which are the most common properties used in JavaBeans. However, the JavaBeans API also supports indexed properties, which are properties that represent an array of values. Indexed properties work in a way very similar to arrays in traditional Java programming: You access a particular value using an integer index. Indexed properties are very useful in situations in which a bean must maintain a group of properties of the same type. For example, a container bean that keeps track of the physical layout of other beans might store references to them in an indexed property.

Bound and Constrained Properties

The JavaBeans API supports two mechanisms for working with properties at a more advanced level: bound and constrained properties. Bound properties are properties that provide notifications to an interested party based on changes in the property value. An interested party is an applet, application, or bean that wants to know about changes in the property. These properties are called bound properties because they are bound to some type of external behavior based on their own changes. Bound properties are defined at the component level, which means that a bean is responsible for specifying which components are bound. An example of a bound property is a visibility property; a bean's container might be interested in knowing the status of this property because the container has to graphically reorganize other beans based on a bean's visibility.

The other interesting property feature provided by the JavaBeans API is support for constrained properties, which are properties that enable an interested party to perform a validation on a new property value before accepting the modification. Constrained properties are useful in providing interested parties with control over how a bean is altered. An example of a constrained property is a date property for which the application containing the bean wants to limit the valid date property values to a certain range.

Introspection

The introspection facilities in the JavaBeans API define the mechanism by which components make their internal structure readily available to the outside world. These facilities consist of the functional overhead necessary to enable development tools to query a bean for its internal structure, including the interfaces, methods, and member variables that comprise the bean. Although the introspection services are primarily designed for use by application builder tools, they are grouped separately from the application builder services in the API because their role in making a bean's internal structure available externally is technically independent of builder tools. In other words, you may have other reasons for querying a bean about its internal structure beyond the obvious reasons used in builder tools.

The introspection services provided by the JavaBeans API are divided into two parts: low-level services and high-level services. These two types of services are distinguished by the level of access they provide to bean internals. The low-level API services are responsible for enabling wide access to the structural internals of a bean. These services are very important for application builder tools that heavily use bean internals to provide advanced development features. However, this level of access isn't appropriate for developers who are using beans to build applications because it exposes private parts of a bean that aren't meant to be used by developers at the application level. For these purposes, the high-level API services are more appropriate.

The high-level services use the low-level services behind the scenes to provide access to limited portions of a bean's internals (typically, the bean's public properties and methods). The difference between the two levels of services is that the high-level services don't enable access to internal aspects of a bean that aren't specifically designed for external use. The end result is two distinct services that offer bean introspection capabilities based on the level of access required by the interested party, be it an application builder tool or a user. The next few sections cover several of the major functions supported in the JavaBeans API introspection facilities.

Reflection and Design Patterns

The JavaBeans API has a very interesting technique for assessing the public properties, methods, and events for a bean. To determine information about a bean's public features, the bean's methods are analyzed using a set of low-level reflection services. These services gather information about a bean and determine its public properties, methods, and events by applying simple design patterns. You learned about the standard Java 1.1 reflection services in Chapter 18, "The Reflection Package." Design patterns are rules applied to a bean's method definitions that determine information about the bean. For example, when a pair of accessor methods are encountered in the analysis of a bean, the JavaBeans introspection facilities match them based on a design pattern and automatically determine the property they access.

The whole premise of design patterns is that method names and signatures conform to a standard convention. There are a variety of different design patterns for determining everything from simple properties to event sources. All these design patterns rely on some type of consistent naming convention for methods and their arguments. This approach to introspection is not only convenient from the perspective of JavaBeans, it also has the intended side effect of encouraging bean developers to use a consistent set of naming conventions.

Explicit Bean Information

Even though the design-pattern approach to introspection is very useful and encourages a consistent approach to naming, you may be wondering what happens if bean developers don't follow the convention. Fortunately, design patterns aren't the only option for introspection, meaning that obstinate developers are free to ignore the suggested naming conventions if they so choose. The developers who opt to cast convention to the wind must use another introspection facility in the JavaBeans API: They must explicitly list the public information about their beans. They must "spill the beans," to inject a painfully bad pun.

The explicit introspection facility in the JavaBeans API to which I'm referring involves creating a bean information class that specifies various pieces of information about a bean, including a property list, method list, and event list. This approach isn't automatic like the design-pattern approach, but it does provide a way to explicitly describe your bean to the world, which might be advantageous in some situations.

The Introspector

Just in case you're wondering how two different introspection approaches can possibly coexist to describe a single bean, you should know about another service that consolidates the whole introspection process. The introspection facilities provide an introspector used to obtain explicit bean information for a bean. The introspector is responsible for traversing the inheritance tree of a bean to determine the explicit bean information for all parent beans. If, at any point, explicit information is not defined, the introspector falls back on the reflection services and uses design patterns to automatically determine external bean information.

This two-tiered solution to assessing bean functionality is very nice because it first attempts to use information explicitly provided by a bean's developer and relies on automatic design patterns only if the explicit information isn't there. The other nice thing is that it supports a mixture of the two approaches, which means that methods for a bean can be explicitly defined in a provided bean information class, but the properties and events can be determined automatically using design patterns. This gives bean developers a lot of flexibility in deciding how they want their beans exposed.

Event Handling

The event-handling facilities in the JavaBeans API specify an event-driven architecture that defines interactions among beans and applications. If you're familiar with the Java AWT, you know that it provides a comprehensive event-handling model. This existing AWT event model forms the basis of the event-handling facilities in the JavaBeans API. These event-handling facilities are critical in that they determine how beans respond to changes in their state, as well as how these changes are propagated to applications and other beans.

The event-handling facilities hinge on the concepts of event sources and listeners. A bean capable of generating events is considered an event source; an application or bean capable of responding to an event is considered an event listener. Event sources and listeners are connected by an event registration mechanism that is part of the event-handling facilities. This registration mechanism basically boils down to an event listener being registered with an event source through a simple method call. When the source generates an event, a specified method is called on the event listener with an event state object being sent along as its argument. Event state objects are responsible for storing information associated with a particular event. In other words, event state objects carry with them any information related to the event being sent. The next few sections cover some of the major issues dealt with by the JavaBeans API event-handling facilities.

Unicast and Multicast Event Sources

Although most practical event sources support multiple listeners, the event-handling facilities provide for event sources that choose to limit their audience to a single listener. These sources are called unicast event sources; their more liberal counterparts are called multicast event sources. The primary functional difference between the two is that unicast event sources throw an exception if an attempt is made to register more than one listener.

Even though the JavaBeans API supports both unicast and multicast event sources, keep in mind that multicast event sources are much less limiting in terms of practical use. In other words, developers should avoid designing beans as unicast event sources whenever possible.

Event Adapters

Even though many bean events follow the standard source/listener model about which you just learned, the JavaBeans API provides a mechanism for dealing with more complex situations for which this model doesn't quite fit the bill. This mechanism is based on event adapters, which act as intermediaries between event sources and listeners. Event adapters sit between sources and listeners and provide a way of inserting specialized event-delivery behavior into the standard source/listener event model. Event adapters are important to the event-handling facilities because they open the door for the implementation of a highly specialized event-handling mechanism tailored to the unique challenges sometimes encountered in applications or application builder tools.

Persistence

The persistence facilities in the JavaBeans API specify the mechanism by which beans are stored and retrieved within the context of a container. The information stored through persistence consists of all the parts of a bean necessary to restore the bean to a similar internal state and appearance. This generally involves the storage of all public properties and, potentially, some internal properties, although the specifics are determined by each particular bean. Information not stored for a bean through persistence are references to external beans, including event registrations. These references are expected to be stored somehow by an application builder tool or through some programmatic means.

By default, beans are persistently stored and retrieved using the automatic serialization mechanism provided by Java, which is sufficient for most beans. However, bean developers are also free to create more elaborate persistence solutions based on the specific needs of their beans. Like the introspection facilities, the JavaBeans persistence facilities provide for both an explicit approach and an automatic approach to carrying out its functions.

Application Builder Support

The final area of the JavaBeans API deals with application builder support. The application builder support facilities provide the overhead necessary to edit and manipulate beans using visual application builder tools. Application builder tools rely heavily on these facilities to enable a developer to visually lay out and edit beans while constructing an application. These facilities fulfill a major design goal of the JavaBeans API: They enable beans to be used constructively with little or no programming effort.

One issue with which the JavaBeans architects wrestled is that application builder support for a specific bean is required only at design time. Consequently, it is somewhat wasteful to bundle this support code into a runtime bean. Because of this situation, the application builder facilities require that builder-specific overhead for a bean must be physically separate from the bean itself. This separation enables beans to be distributed by themselves for runtime use or in conjunction with the application builder support for design-time use. The next two sections cover some of the major issues dealt with by the JavaBeans API application builder support facilities.

Property Editors and Sheets

One of the ways in which the JavaBeans API supports the editing and manipulation of beans with application builder tools is through property sheets. A property sheet is a visual interface that provides editors for each public property defined for a bean. The individual editors used in a property sheet are called property editors. Each type of exported property in a bean must have a corresponding property editor if it is to be edited visually by a builder tool. Some standard property editors are provided by the JavaBeans API for built-in Java types, but user- defined properties require their own custom editors. The property editors for all the exported properties of a bean are presented together on a property sheet that enables users to edit the properties visually.

Customizers

The other way in which the JavaBeans API enables beans to be visually edited in an application builder tool is through customizers. Customizers are user interfaces that provide a specialized way of visually editing bean properties. Because customizers are implemented entirely by bean developers, there are no firm guidelines about how they present visual property information to the user. However, most customizers probably will be similar in function to "wizards," those popular user interfaces on the Windows platform that use multiple-step questionnaires to gather information from the user.

Summary

This chapter took you inside the JavaBeans technology by exploring the JavaBeans API. This API is ultimately responsible for delivering all the functionality of JavaBeans. You learned that the API has several major functional areas, each of which is devoted to a particular JavaBeans service. You covered the basics of each of these areas and looked at the kinds of problems they address and the different solutions they provide.

Although the discussions throughout this chapter were fairly general and avoided much technical detail, they still painted a pretty complete picture of the JavaBeans API--at least from a conceptual level. Armed with this knowledge, you're ready to press on and learn how to use the JavaBeans API in the next chapter, "Creating Your Own Beans." Roll up your sleeves and get ready for more thrills!

TOCBACKFORWARDHOME


©Copyright, Macmillan Computer Publishing. All rights reserved.