Chapter 22. JavaBeans

JavaBeans is a design pattern and a component architecture for Java. It is a set of rules for writing highly reusable software elements that can be understood by both developers and development tools. Writing components to the JavaBeans specification means your code will be easier to read and you won’t have to write as much custom code to glue components together. It also allows you to leverage JavaBean-aware development environments that can recognize the features of these components automatically and connect them in a plug-and-play fashion to build parts of applications.

In this chapter, we’ll use the NetBeans IDE to create simple applications by connecting Java beans visually. We will also create our own reusable beans to add to the palette of components in the IDE. Although this type of visual application design has never quite reached the level it was expected to (we’ll talk about some of the reasons why later), it is still very useful in GUI development. Perhaps more important though, the fundamental JavaBeans patterns are firmly entrenched in all aspects of the core Java APIs, so understanding them is important. We will cover all of these aspects in this chapter, including hand-coding with Java beans and some related APIs.

What’s a Bean?

What exactly is or are JavaBeans? JavaBeans (the architecture) defines a set of rules; Java beans are ordinary Java objects that play by these rules. That is, Java beans are Java objects that conform to the JavaBeans API and design patterns. By doing so, they can be recognized and manipulated by tools (especially visual application builder environments) as well as by hand coding. Beans live and work in the Java runtime system, as do all Java objects. They communicate with their neighbors using events and other normal method invocations.

For examples of Java beans, we need look no further than the javax.swing packages. All the familiar components, such as JButton, JTextArea, and JScrollpane, follow the JavaBeans design patterns and are beans. Much of what you learned in Chapter 16 about Swing components prepared you for understanding beans. Although most of the Swing components aren’t very useful in isolation, in general, beans can also be large and complex application components, such as spreadsheets or document editors. We’ll talk more about exactly what makes a bean a bean in a moment. For now, we want to give you a better sense of how they are used.

One of the goals of JavaBeans is to allow components to be manipulated visually within a graphical application builder. Beans can be chosen from a palette of tools and manipulated graphically by an application designer. The Swing components we mentioned earlier are obvious candidates for this kind of usage. But Java beans can be not only simple UI components, such as buttons and sliders, but also more complex and abstract components. It is easy to get the impression that beans are, themselves, always graphical objects, but Java beans can implement any part of an application, including “invisible” parts that perform calculations, storage, and communications. Three characteristics of the JavaBeans architecture aim to make it possible to work with application components in this way:

Design patterns

The most important characteristic of a Java bean is simply a layer of standardization. Design patterns (i.e., coding conventions) let tools and humans recognize the basic features of a bean and manipulate it without knowing how it is implemented. We might say that beans are “self-documenting.” By examining a bean, we can tell what events it can fire and receive; we can also learn about its properties (the equivalent of its public variables) and methods. Beans can also provide explicit (“bean info”) information about their features tailored specifically for IDEs.

Reflection

Reflection is an important feature of the Java language. (It’s discussed in Chapter 7.) Reflection makes it possible for Java code to inspect and manipulate new Java objects at runtime. In the context of JavaBeans, reflection lets a development tool analyze a bean’s capabilities, examine the values of its fields, and invoke its methods. Essentially, reflection allows Java objects that hook up at runtime to do all the things that could be done if the objects had been put together at compile time. Even if a bean doesn’t come bundled with any “built-in” documentation, we can still gather information about its capabilities and properties by directly inspecting the class using reflection.

Object serialization

Finally, the Java Serialization API allows us to “freeze-dry” a live application or application component and revive it later. This is an important capability that makes it possible to piece together applications without extensive code generation. Rather than customizing and compiling large amounts of Java code to build our application on startup, we can simply configure beans, tweak their appearance, and save them. Later, the beans can be restored with all their state and interconnections intact. This makes possible a fundamentally different way of thinking about the design process. It is easy to use serialized objects from handwritten Java code as well, so we can freely mix serialized beans with plain-old bean classes and other Java code. There is also a “long-term” object serialization mechanism that saves Java beans in an XML format that is very resilient to changes in classes.

What Constitutes a Bean?

The bean examples we mentioned have ranged from simple buttons to spreadsheets. Obviously, a button bean would be much less complex than a spreadsheet and would be used at a different level of the application’s design. At what level are beans intended to be used? The JavaBeans architecture is supposed to scale well from small to large; simple beans can be used to build larger beans. A small bean may consist of a single class; a large bean may have many. Beans can also work together through their container to provide services to other beans.

Simple beans are little more than ordinary Java objects. In fact, any Java class that has a default (empty) constructor could be considered a bean. A bean should also be serializable, although the JavaBeans specification doesn’t strictly require that. These two criteria ensure that we can create an instance of the bean dynamically and that we can later save the bean as part of a group or composition of beans. There are no other requirements. Beans are not required to inherit from a base bean class, and they don’t have to implement any special interface.

A useful bean should send and receive events and expose its properties to the world. To do so, it follows the appropriate design patterns for naming the relevant methods so that these features can be automatically discovered. Most nontrivial beans intended for use in a visual application builder IDE also provide information about themselves in the form of a BeanInfo class. A BeanInfo class implements the BeanInfo interface, which holds methods that describe a bean’s features in more detail, along with extra packaging, such as icons for display to the user. Normally, this “bean info” is supplied by a separate class that is named for and supplied with the bean.

The NetBeans IDE

We can’t have a full discussion of beans without spending a little time talking about the builder environments in which they are used. In this chapter, we use the NetBeans IDE version 7.2 to demonstrate our beans. NetBeans is a popular, pure Java development environment. In this case, the integrated in integrated development environment means that NetBeans offers powerful source and visual editor capabilities, templates that aid in the creation of various types of Java classes, and the ability to compile, run, and debug applications, all in one tool. In particular, we’ll be using the visual development environment of NetBeans to glue together our Java beans and try them out. Other IDEs offer similar capabilities. See Appendix A for a brief comparison of NetBeans and the Eclipse IDE. We’ve chosen NetBeans to use in this chapter because its mature GUI builder environment makes it easy to illustrate the concepts here.

Because NetBeans is a full-blown production development environment, it has many features we don’t use in these examples. For that reason, we can’t really provide a full introduction to it here. We will provide only bare-bones directions here for demonstrating the Java beans in this chapter. Most of the techniques you see here will apply in some form in other IDEs as well.

Installing and Running NetBeans

You should install Java 7.0 before you install NetBeans. If you installed the JDK from Sun’s website, you may have downloaded a combined JDK and NetBeans bundle, so you may already have it installed. The standalone installation of NetBeans can be found at http://www.netbeans.org. Follow the simple installation instructions for those packages (you may have to reboot if you just installed Java). When you’re all set, launch NetBeans. When you first start NetBeans, a welcome screen appears. Close it for now by clicking the small x on its tab. (If you want to return to this welcome screen later to take the NetBeans tutorials, choose Help Welcome Screen.)

Installing our example beans

Before we get started, we’ll have to add the example beans used in this chapter to the NetBeans palette. NetBeans installs Java beans in a central location that can be used by multiple projects in the editor.

  1. To install our beans, grab our demonstration beans JAR file, magicbeans.jar, from this book’s website.

  2. Save the file locally and then select Tools Palette Swing/AWT Components to add the beans.

  3. Click “Add from Jar,” then navigate to and select the magicbeans.jar file and click Next. The wizard then shows you a list of beans that our JAR contains (there should be eight altogether).

  4. Select all of them (click the first and shift-click the last), then click Next.

  5. NetBeans prompts you for the palette category under which you wish to file these; select Beans (which would otherwise be empty), then click Finish and Close.

We’ll see these beans soon when we start editing an application.

Creating a project and file

Now, we must create a new project to hold our work. To create a new project, select New Project from the File menu. In the Categories pane of the wizard, select General and in the Projects pane, select Java Application, and then click Next. Give your project a name, such as LearningJava, and specify a location or leave the defaults. Uncheck the box labeled Create Main Class because we will create our own, then click Finish to create our empty project. If this is the first time you’ve created a project in NetBeans, you may see a message that says that NetBeans is scanning project classpaths; this may take a few minutes.

Next, we need to create a class file to put into our project. Select New File from the File menu. NetBeans prompts you with a wizard. In the Categories pane, select Java GUI Forms and in the File Types pane, select JFrame Form. Choosing JFrame Form gives us a Java class file extending JFrame with the basic structure of a GUI application already set up for us. Click Next, then give the file a name, such as LearningJava1. You may leave the package set to the default package if you wish. Now click Finish; the screen looks like Figure 22-1.

The NetBeans workspace

Figure 22-1 shows the NetBeans application. The screen has three main areas with a toolbar at the top. The left area is the explorer window. Tabs in the explorer window can show a Java package and class-oriented view of our project, a filesystem view, or a runtime environment view. The explorer is shown with our LearningJava1.java class selected. The bottom left is the Navigator area, which shows the methods and properties of the class, and in the case of a GUI component the child component layout within it. In the center area is our workspace with tabs for each open file (currently one). Because we selected a GUI-type file, NetBeans has placed us into GUI “design” mode and shows us an empty box where we will place our beans. Click alternately on the Source and Design buttons to switch between the Java source code and this view (try it out).

On the right side are a Palette pane and a Properties pane, which is currently showing some properties of the currently selected file, but will show the properties of the currently selected bean component when we add one to the design area. The Palette has groupings for different types of beans. The Swing group includes all the standard Swing components. AWT holds older AWT components. Layouts holds Java layout managers.

The NetBeans workspace
Figure 22-1. The NetBeans workspace

Under Palette, select Swing (it may be selected by default) to see some of the available Swing components (they appear as icons at the top of the window). Now scroll down and select Beans to see the beans we imported earlier. You should see the friendly Dial component bean from Chapter 18, along with a tiny person bean. The rest of our beans lack pretty icons because these example beans aren’t packaged with them. (We’ll talk about packaging later in the chapter.) Figure 22-2 shows the bean palette.

To place a bean into the workspace, click on it and then click in the workspace. Before you do that, though, you may want to set an appropriate layout manager. The Inspector holds a tree that shows all the components (visible and invisible) in the project. By right-clicking on the JFrame (our top-level container) in either the workspace or the tree, you can select Set Layout to specify the layout manager for the frame. For now, try using AbsoluteLayout, provided by NetBeans. This allows you to arbitrarily place and move beans within the container. You wouldn’t want to do this in general, but for our examples it will make life a bit easier. The other layout managers are easy enough to use, but we’ll refer you to NetBeans tutorials for the details.

The bean palette
Figure 22-2. The bean palette

Properties and Customizers

Properties represent the “state” or “data” content of a bean. These features can be manipulated externally to configure the bean. For a bean that’s a GUI component, you might expect its properties to include its size, colors, and other features of its basic appearance. Properties are similar in concept to an object’s public variables. Like a variable, a property can be a primitive type (such as a number or Boolean), or it can be a complex object type (such as a String or a collection of spreadsheet data). Unlike variables, properties are always manipulated using methods to set and get the value; this enables a bean to take action whenever a property changes. By sending an event when a property changes, a bean can notify other interested beans of the change (which we will discuss later in this chapter).

Let’s pull a couple of beans into NetBeans and take a look at their properties. Click on a button (this will be a JButton) from the Swing Controls group of the palette, and then click in the workspace. When the JButton was first loaded by NetBeans, it was inspected to discover its properties. When we select an instance of the button, NetBeans displays these properties in the Properties pane and allows us to modify them.

The button has about eight basic properties, followed by a few additional groupings. The list called Other Properties adds more detail. There is also a Layout properties section (these are in actuality not properties of the JButton, but are here for convenience) as well as an Accessibility properties list (for components that have accessibility-related properties). The foreground and background properties are colors; their current values are displayed in the corresponding box. font is the font for the label text; an example of the font is shown. text is the text of the button’s label. You can also set an image icon for the button, the tooltip text that appears when the mouse hovers over the item, and a keyboard shortcut identifier, called a mnemonic. Try typing something new for the value of the text property and hit return to see the button label change. Click on the background color to enter a numeric color value, or, better yet, press the “...” button to pop up a color-chooser dialog.

Most of these basic properties will be familiar to you because many GUI beans inherit them from the base JComponent class. The Other Properties section lists almost 50 additional properties inherited from JComponent. NetBeans is making an effort to categorize these for us. As we’ll see when we create our own beans, we can limit which properties are included in the Properties pane.

Now place a Juggler bean in the workspace (this is one of Sun’s original demonstration Java beans that we have updated). The animation starts, and the juggler begins juggling some roughly drawn beans, as shown in Figure 22-3. If he gets annoying, don’t worry; we’ll have him under our control soon enough.

You can see that this bean has a different set of properties, including an interesting one called animationRate. It is an integer property that controls the delay in milliseconds between displays of the juggler’s frames. Try changing its value. The juggler changes speed as you type each value. Good beans give you immediate feedback when you change their properties. Uncheck the checkbox next to the Boolean juggling property to stop the show if you want.

Notice that the Properties pane provides a way to display and edit each of the different property types. For the foreground and background properties of the JButton, the pane displays the color; if you click on them, a color selection dialog pops up. Similarly, if you click on the font property, you get a font selection dialog. For integer and string values, you can type a new value into the field. NetBeans understands and can edit the most useful basic Java types.

Since the property types are open-ended, beans with more complex property types can supply their own property editor. The Molecule bean that we’ll play with in the next section, for example, uses a custom property editor that lets us choose the type of molecule. If it needs even more control over how its properties are displayed, a bean can provide a customizer, which allows a bean to provide its own GUI for editing its properties. (For example, a customizer could let you draw an icon for a button.)

Juggling beans
Figure 22-3. Juggling beans

Event Hookups and Adapters

Beans use events to communicate. As we mentioned in Chapter 16, events are not limited to GUI components but can be used for signaling and passing information in more general applications. An event is simply a notification; information describing the event and other data are wrapped up in a subclass of EventObject and passed to the receiving object by a method invocation. Event sources register listeners that want to receive the events when they occur. Event receivers implement the appropriate listener interface containing the method needed to receive the events. This is Java’s general event mechanism in a nutshell.

It’s often useful to place an adapter between an event source and a listener. An adapter can be used when an object doesn’t know how to receive a particular event; it enables the object to handle the event anyway. The adapter can translate the event into some other action, such as a call to a different method or an update of some data. One of the jobs of NetBeans is to help us hook up event sources to event listeners. Another job is to produce adapter code that allows us to hook up events in more complex ways.

Taming the Juggler

Let’s get our juggler under control with the following steps:

  1. Using the Properties pane, change the label of your button to read “Start.”

  2. Now click the small Connection Mode icon at the top of the GUI builder (the second icon, showing two items with arrows pointing at one another).

  3. After pressing the button, NetBeans is waiting for us to select two components to “hook up.” Click first on the Start button and then on the Juggler. NetBeans pops up the Connection Wizard, indicating the source component (the button) and prompting you to choose from a large list of events (see Figure 22-4). Most of them are standard Swing events that can be generated by any kind of JComponent. What we’re after is the button’s action event.

  4. Expand the folder named action, and select actionPerformed as the source event.

  5. At the bottom of the dialog box NetBeans indicates the name of an event handler method that it will generate for us. Leave the method name as is. Click Next to go to the Specify Target Operation screen for the Juggler.

  6. The wizard prompts us to choose a property to set on the Juggler, as shown in Figure 22-5. The display shows three of the Juggler’s properties. Choose the juggling property as the target and click Next.

  7. Enter true in the Value field and click Finish. NetBeans takes you to the source view and shows you the method it has generated to respond to the button action.

We have completed a hookup between the button and the Juggler. When the button fires an action event, the juggling property of the Juggler is set to true.

Scroll around the source view and take a look at the code that NetBeans has generated to make this connection for us. Specifically, in the initComponents() method of our class, it has created an anonymous inner class to serve as the ActionListener for ActionEvents from our button (which it has named jButton1):

    jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });

The adapter calls a private method that sets the property on our Juggler:

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        juggler1.setJuggling(true);
    }
Selecting a source event in the Connection Wizard
Figure 22-4. Selecting a source event in the Connection Wizard
Specifying a target operation in the Connection Wizard
Figure 22-5. Specifying a target operation in the Connection Wizard

You’ll notice that most of the code that was written for us is shaded grey to indicate that it is autogenerated code and can’t be directly modified. The body of the private method is open, however, and we could modify it to perform arbitrary activities when the button is pushed. In NetBeans, the hookup is just a starting point.

This may all seem a little obtuse. After all, if we had made the Juggler an ActionListener in the first place, we would expect to hook it directly to the button. The use of adapters provides a great deal of flexibility, however, as we’ll see next.

To complete our example, click the Design button, then repeat the process, adding a second JButton labeled “Stop.” We could implement the Stop button in the same way that we did the Start button, by passing a specific value to the juggling method, but we’re going to try an alternative here. Click the Connection Wizard icon; select the Stop button and the Juggler as its target. Again, choose the actionPerformed method as the source, but this time, instead of selecting a property on the Juggler, click the Method Call radio button to see a list of available methods on the Juggler bean. Scroll all the way down and select the stopJuggling() method. Click Finish to complete the hookup, and look at the generated code if you wish. With this, we have seen an example of hooking up a source of action events to generate an arbitrary method call on a bean. (Of course, there is a startJuggling() method as well, which we could have used for the first button.)

Running the example

Now, the Juggler will do our bidding. Right-click on the LearningJava1.java file in the Projects tab of the Explorer pane (or in the source view of the file) and select Run File. Watch as NetBeans compiles and runs our example. You should be able to start and stop the juggler using the buttons! When you are done, quit the juggler application and return to the GUI editor. Close this example by closing its tab in the workspace, and let’s move on. (There is no need to save the file explicitly; NetBeans saves automatically as you edit.)

Molecular Motion

Let’s look at one more interesting example, shown in Figure 22-6. Create a new file in our project as before, choosing Java GUI Forms from the Categories pane and JFrame Form in the File Types pane. Call this file LearningJava2.

Grab a Molecule bean and place it in the workspace. (The default BorderLayout maximizes its area if you place the bean in the center.) If you run the example now, you will see that by dragging the mouse within the image, you can rotate the model in three dimensions. Try changing the type of molecule by using the Properties pane: ethane is fun.[45]

Let’s see what we can do with our molecule. Grab a Timer bean from the palette. Timer is a clock.[46] Every so many milliseconds, Timer fires an event. The timer is controlled by an long property called delay, which determines the number of milliseconds between events. Timer is an “invisible” bean; it is not derived from a JComponent and doesn’t have a graphical appearance, just as an internal timer in an application doesn’t normally have a presence on the screen. NetBeans shows these invisible beans just like any other bean in the Navigator pane on the left. When you wish to select the Timer, click on it in the tree in the Navigator pane.

Let’s hook the Timer to our Molecule. Start the Connection Wizard and select the Timer (from the tree) and then the Molecule. Choose the Timer’s timerFired() event from the list (expand the folder to display it). Click Next and select the Method Call radio button. Find and select the rotateOnX() method and click Finish. Run the example. Now the Molecule should turn on its own every time it receives an event from the timer. Try changing the timer’s delay property. You can also hook the Timer to the Molecule’s rotateOnY() method. Use a different instance of Timer and, by setting different delay values, make it turn at different rates in each dimension. Fun!

The Molecule bean and the Timer
Figure 22-6. The Molecule bean and the Timer

Binding Properties

By using a combination of events and adapters, we can connect beans in many interesting ways. We can even “bind” two beans together so that if a property changes in the first bean, the corresponding property is automatically changed in the second bean. In this scenario, the beans don’t necessarily have to be of the same type, but in order to make sense, the properties do.

Close the Molecule file and start a new one. Grab two NumericField beans from the palette, drop them in the workspace, and select one of them. You’ll probably want to set the AbsoluteLayout again. You can also adjust the width of the fields by dragging them at the sides. You’ll notice that a NumericField has many of the standard properties of a Swing component. If you look in the Other Properties section of the Properties pane, you can find an integer property called value that represents the numeric value of the field. You can set it there or enter a number directly into the field when you run the program. NumericField rejects nonnumeric text.

Let’s bind the value property of one of the fields to the other. Activate the Connection Wizard to create a connection between the two fields. Click first on numericField1 and then on numericField2 so that numericField1 is the source. In the wizard, choose the propertyChange() event of the source field. This is the listener method for PropertyChangeEvent, a generic event sent by beans when one of their properties changes. When a bean fires property change events in response to changes in a particular property, that property is said to be “bound.” This means that it is possible to bind the property to another bean through the generic mechanism. In this case, the value property of our NumericField beans is a bound property, so whenever it changes, a PropertyChangeEvent is fired.

Choose Next, and select the value property as the target for numericField2. Click Next again, and select the Property radio button on the Parameters screen. Click the “...” editor button to pop up a Select Property dialog. Select the source numeric field (probably named numericField1, if that is your source button) from the pull-down menu, and then choose the value property. Click OK and Finish to complete the hookup.

Run the application, and try entering values in the first field (numericField1). The second field should change each time. The second bean’s value property has been bound to the first.

Try binding the value property in the other direction as well so that you can change the value in either bean, and the changes are propagated in both directions. (Some simple logic in the beans prevents infinite loops from happening here.)

NetBeans has again generated an adapter for us. This time, the adapter listens for PropertyChangeEvents and invokes the setValue() method of our target field. We haven’t done anything earth shattering. The PropertyChangeEvent does carry some extra information—the old and new values of the property—but we’re not using them here. And with the Connection Wizard, you can use any event source as the impetus to set a property on your target bean. Finally, as we’ve seen, the property can derive its value from any other bean in the layout. The flexibility of the Connection Wizard is, to some extent, masking the purpose of the events, but that’s OK. If we are interested in the specific property that changed, or if we want to apply logic about the value, we can fill in the generated method with our own code.

Many Swing components have bound properties, which are usually documented in the Javadoc for the class.

Constraining Properties

In the previous section, we discussed how beans fire PropertyChangeEvents to notify other beans (and adapters) that a property has changed. In that scenario, the object that receives the event is simply a passive listener as far as the event’s source is concerned. JavaBeans also supports constrained properties, in which the event listener gets to say whether it will allow a bean to change the property’s value. If the new value is rejected, the change is cancelled; the event source keeps its old value.

The concept of constrained properties has not been heavily used in the normal operation of Swing, so we won’t cover it in detail here. But it goes something like this. Normally, PropertyChangeEvents are delivered to a propertyChange() method in the listener. Constrained properties are implemented by delivering PropertyChangeEvents to a separate listener method called vetoableChange(). The vetoableChange() method throws a PropertyVetoException if it doesn’t like a proposed change. In this way, components can govern the acceptable values set by other components.

Building Beans

Now that you have a feel for how beans look from the user’s perspective, let’s build some. In this section, we will become the Magic Beans Company. We will create some beans, package them for distribution, and use them in NetBeans to build a very simple application. (The complete JAR file, along with all the example code for this chapter, is online at http://oreil.ly/Learn_Java_4E.)

The first thing we’ll remind you of is that absolutely anything can be a bean. Even the following class is a bean, albeit an invisible one:

    public class Trivial implements java.io.Serializable {}

Of course, this bean isn’t very useful: it doesn’t have any properties, and it doesn’t do anything. But it’s a bean nonetheless, and we can drag it into NetBeans as long as we package it correctly. If we modify this class to extend JComponent, we suddenly have a graphical bean that be seen in the layout, with lots of standard Swing properties, such as size and color information:

    public class TrivialComponent extends JComponent {}

Next, let’s look at a bean that’s a bit more useful.

The Dial Bean

We created a nifty Dial component in Chapter 18. What would it take to turn it into a bean? Surprise: it is already a bean! The Dial has a number of properties that it exposes in the way prescribed by JavaBeans. A get method retrieves the value of a property; for example, getValue() retrieves the dial’s current value. Likewise, a set method, setValue(), modifies the dial’s value. The dial has two other properties, which also have get and set methods: minimum and maximum. This is all the Dial needs to inform a tool such as NetBeans what properties it has and how to work with them. Because Dial is a JComponent, it also has all the standard Swing properties, such as color and size. The JComponent provides the set and get methods for all its properties.

To use our Dial, we’ll put it in a Java package named magicbeans and store it in a JAR file that can be loaded by NetBeans. The source code, which can be found online, includes an Ant build file (see Chapter 15) that compiles the code and creates the final JAR file.

If you were starting from scratch, it would go like this: first, create a directory called magicbeans to hold our beans, add a package statement to the source files Dial.java, DialEvent.java, and DialListener.java (from Chapter 18), put the source files into the magicbeans directory, and compile them (using the command javac magicBeans/Dial.java) to create class files.

Next, we need to create a manifest file that tells NetBeans which of the classes in the JAR file are beans and which are support files or unrelated. At this point, we have only one bean, Dial.class, so create the following file, called magicBeans.manifest:

    Name: magicbeans/Dial.class
    Java-Bean: True

The Name: label identifies the class file as it will appear in the JAR: magicbeans/Dial.class. Specifications appearing after an item’s Name: line and before an empty line apply to that item. (See Chapter 3 for more details.) We have added the attribute Java-Bean: True, which flags this class as a bean to tools that read the manifest. We will add an entry like this for each bean in our package. We don’t need to flag support classes (such as DialEvent and DialListener) as beans because we won’t want to manipulate them directly with NetBeans; in fact, we don’t need to mention them in the manifest at all.

To create the JAR file, including our manifest information, enter this command:

    % jar -cvmf magicbeans.manifest magicbeans.jar magicbeans/*.class

If you loaded the precompiled examples as instructed earlier, then you already have the Dial bean loaded into NetBeans. The version supplied in the precompiled magicbeans.jar file has additional packaging that allows it to appear with a spiffy icon in the palette, as we’ll discuss a bit later. (If you haven’t loaded the example JAR, you can import the one we just created by selecting Palette → Swing/AWT Components dialog from the Tools menu, as described earlier in this chapter.) If you want to replace the Dial bean on your palette, you can remove it by right-clicking on the icon and selecting Delete before importing the new JAR. (Actually, NetBeans 7.2 should reload the JAR automatically if you overwrite it.)

You should now have an entry for Dial in the bean palette. Drop an instance of the Dial bean into a new JFrame Form file in NetBeans.

As Figure 22-7 shows, the Dial’s properties—maximum, minimum, and value—appear in the Properties pane and can be modified by NetBeans. If you just created the Dial JAR following our minimal instructions, you’ll see these properties along with all the Swing properties inherited from the JComponent class. The figure shows the Dial bean as it appears later in this chapter (with the supplied packaging), after we’ve learned about the BeanInfo class. We’re almost there.

Now we’re ready to put the Dial to use. Reopen the Juggler file that we created in the first section of this chapter. Add an instance of our new magic Dial bean to the scenario, as shown in Figure 22-8.

Bind the value property of the Dial to the animationRate of the Juggler. Use the Connection Wizard, as before, selecting the Dial and then the Juggler. Select the DialEvent source and bind the animationRate property, selecting the Dial’s value as the property source. When you complete the hookup, you should be able to vary the speed of the juggler by turning the dial. Try changing the maximum and minimum values of the dial to change the range.

The Dial component as a bean
Figure 22-7. The Dial component as a bean
The Juggler with a dialable animation rate
Figure 22-8. The Juggler with a dialable animation rate

Design Patterns for Properties

We said earlier that tools such as NetBeans found out about a bean’s properties by looking at its get and set methods. The easiest way to make properties visible is to follow these simple design patterns:

  • Method for getting the current value of a property:

        public PropertyType getPropertyName()
  • Method for setting the value of a property:

        public void setPropertyName( PropertyType arg )
  • Method for determining whether a Boolean-valued property is currently true:

        public boolean isPropertyName()

The last method is optional and is used only for properties with Boolean values. (You could use the get method for Boolean values as well.)

The appropriate set and get methods for these features of our bean are already in the Dial class, either methods that we added or methods inherited from the java.awt.Component and javax.swing.JComponent classes:

    // inherited from Component
    public Color getForeground()
    public void setForeground(Color c)
      
    public Color getBackground()
    public void setBackground(Color c)
      
    public Font getFont()
    public void setFont(Font f)
      
    // many others from Component and JComponent

    // part of the Dial itself
    public int getValue()
    public void setValue(int v)
      
    public int getMinimum()
    public void setMinimum(int m)
      
    public int getMaximum()
    public void setMaximum(int m)

JavaBeans allows read and write-only properties, which are implemented simply by leaving out the get or set method.

NetBeans uses the Reflection API to find out about the Dial bean’s methods; it then uses these naming conventions to learn what properties are available. When we use the properties editor to change a value, NetBeans dynamically invokes the correct set method to change the value.

If you look further at the JComponent class, you’ll notice that other methods match the design pattern. For example, what about the setCursor() and getCursor() pair? NetBeans doesn’t know how to display or edit a cursor, and we didn’t supply an editor, so it ignores those properties in the properties sheet.

NetBeans automatically pulls the property’s name from the name of its accessor methods; it then lowercases the name for display on the properties sheet. For example, the font property is derived from getFont. Later, we’ll show how to provide a BeanInfo class that overrides the way these properties are displayed, which allows you to provide your own friendly property names. Again, if you used the Dial bean from our precompiled example JAR, you’ll see only our three Dial properties. The JComponent properties are hidden by our packaging a BeanInfo class that determines the properties we wish to show.

Generating bean patterns in NetBeans

NetBeans automatically recognizes JavaBeans getter and setter method patterns in classes. In the source code view, select the Source menu Insert Code option and choose Getter and Setter to automatically generate getter and setter methods for fields in your class. This can save you a bit of typing if you need to add a lot of properties.

Limitations of Visual Design

These examples have pointed to the idea that we can create at least a trivial application by hooking beans together in a mostly visual way. In other development environments, this kind of bean hookup has been pushed even further. For example, Sun’s original “BeanBox” experimental Java bean container took a different approach than NetBeans. It allowed the developer to work with “live” Java bean instances, dynamically generating adapter code at runtime and relying solely on object serialization to save the resulting work. This kind of design is, in a sense, the real goal of the JavaBeans architecture. It is true “what you see is what you get” (WYSIWYG) programming. However, pure visual design without the ability to integrate handwritten code, as we can do in NetBeans, has not yet proven to scale beyond these kinds of simple applications, and pure visual programming environments beyond just GUI screen layout have thus far failed to catch on.

Serialization Versus Code Generation

If you’ve been keeping an eye on the NetBeans source window while we’ve been working, you may have noticed the code that is being generated when you modify properties of beans. By default, NetBeans generates method calls to set values on beans in the initComponents() method. For example, if you set the value of one of your NumericField beans to 42 in the Properties pane, this value gets hardcoded into the application as an initial value of the bean by a call to setValue() on the bean object at initialization time. But if you click on the Code button in the Properties pane, you’ll see that we have another option. This area holds properties that govern how NetBeans generates the application code. By changing the Code Generation property from Generate Code to Serialize, you change NetBeans’ behavior. Instead of generating method calls in the source code, it saves your fully configured bean as a serialized object and then generates the appropriate code to load the freeze-dried bean into the application from a file.

Try changing the code generation property for a Juggler bean to Serialize. Switching to the source code view and looking at the initComponents() method, you’ll see a line for that bean that uses the static Beans.instantiate() method to load a serialized copy of the bean.

NetBeans treats the serialized bean file as part of the source code and will regenerate it whenever it saves the source file. In order to run this example, we must first perform a manual build. Select Build Build Main Project, then you can run the file as before with the Run File context menu. The reason for the explicit build is to prompt NetBeans to copy the serialized bean file from the source folder of your source file over to the compiled classes directory (it should be smart enough to do this itself). You should see the serialized bean file, named something like: LearnJava1_juggler1.ser alongside your source file (and deployed to the classes directory). You can run the example and confirm that it behaves exactly like the code-generated version. (This is pretty neat if you think about it.)

We’ll discuss working with serialized beans in more detail later in this chapter and ask you to refer to this stored bean file.

Customizing with BeanInfo

So far, everything NetBeans has known about our beans has been determined by low-level reflection—that is, by looking at the methods of our classes. The java.Beans.Introspector class gathers information on a bean using reflection, then analyzes and describes a bean to any tool that wants to know about it. The introspection process works only if the class follows the JavaBeans naming conventions for its methods; furthermore, it gives us little control over exactly what properties and events appear in NetBeans menus. For example, we’ve seen that NetBeans by default shows all the stuff we inherit from the base Swing component. We can change that by creating BeanInfo classes for our beans. A BeanInfo class provides the JavaBeans introspector with explicit information about the properties, methods, and events of a bean; we can even use it to customize the text that appears in menus in NetBeans (and in other IDEs).

A BeanInfo class implements the BeanInfo interface. That’s a complicated proposition; in most situations, the introspector’s default behavior is reasonable. Instead of implementing the BeanInfo interface, we extend the SimpleBeanInfo class, which implements all of BeanInfo’s methods. We can override specific methods to provide the information we want; when we don’t override a method, we’ll get the introspector’s default behavior.

In the next few sections, we’ll develop the DialBeanInfo class that provides explicit information about our Dial bean.

Getting Properties Information

We’ll start out by describing the Dial’s properties. To do so, we must implement the getPropertyDescriptors() method. This method simply returns an array of PropertyDescriptor objects—one for each property we want to publicize.

To create a PropertyDescriptor, call its constructor with two arguments: the property’s name and the class. In the following code, we create descriptors for the Dial’s value, minimum, and maximum properties. We next call a few methods of the PropertyDescriptor class to provide additional information about each property. If our methods were bound (generated PropertyChangeEvents when modified), we’d call the setBound() method of their PropertyDescriptors. Our code is prepared to catch an IntrospectionException, which can occur if something goes wrong while creating the property descriptors, such as encountering a nonexistent method:

    //file: DialBeanInfo.java
    package magicbeans;
    import java.beans.*;
      
    public class DialBeanInfo extends SimpleBeanInfo {
      
      public PropertyDescriptor[] getPropertyDescriptors() {
        try {
          PropertyDescriptor value =
            new PropertyDescriptor("value", Dial.class);
          PropertyDescriptor minimum =
            new PropertyDescriptor("minimum", Dial.class);
          PropertyDescriptor maximum =
            new PropertyDescriptor("maximum", Dial.class);

          return new PropertyDescriptor [] { value, minimum, maximum };
        }
        catch (IntrospectionException e) {
          return null;
        }
      }
    }

Perhaps the most useful thing about DialBeanInfo is that by providing explicit information for our properties, we automatically hide other properties that introspection might find. After compiling DialBeanInfo and packaging it with the Dial, you’ll see that its JComponent properties no longer appear in the NetBeans properties editor. (This has been the case all along if you started with the precompiled example JAR.)

A PropertyDescriptor can provide a lot of other information about a property: the names of the accessor methods (if you decide not to use the standard naming convention), information about whether the property is constrained, and a class to use as a property editor (if the standard property editors aren’t sufficient).

Getting events information

The Dial bean defines its own event: the DialEvent. We’d like to tell development tools about this event so that we can build applications using it. The process for telling the world about our event is similar to what we did previously: we add a method to the DialBeanInfo class called getEventSetDescriptors(), which returns an array of EventSetDescriptors.

Events are described in terms of their listener interfaces, not in terms of the event classes themselves, so our getEventSetDescriptors() method creates a descriptor for the DialListener interface. Here’s the code to add to the DialBeanInfo class:

    public EventSetDescriptor[] getEventSetDescriptors() {
      try {
        EventSetDescriptor dial = new EventSetDescriptor(
          Dial.class, "dialAdjusted",
          DialListener.class, "dialAdjusted");
        dial.setDisplayName("Dial Adjusted");

        return new EventSetDescriptor [] { dial };
      }
      catch (IntrospectionException e) {
        return null;
      }
    }

In this method, we create an EventSetDescriptor object: dial. The constructor for an EventSetDescriptor takes four arguments: the class that generates the event, the name of the event (the name that is displayed, by default, by a development tool), the listener class, and the name of the method to which the event can be delivered. (Other constructors let you deal with listener interfaces that have several methods.) After creating the descriptor, we call the setDisplayName() method to provide a friendly name to be displayed by development tools such as NetBeans. (This overrides the default name specified in the constructor.)

Just as the property descriptors we supply hide the properties that were discovered by reflection, the EventSetDescriptors can hide the other events that are inherited from the base component classes. In theory, when you recompile DialBeanInfo, package it in a JAR, and load it into NetBeans, you should see only the two events that we have explicitly described: our own DialEvent and PropertyChangeEvent (displayed as “Dial Adjusted” and “Bound property change”). Unfortunately, the current version of NetBeans ignores this information.

Once we have an EventSetDescriptor, we can provide other kinds of information about the event. For example, we can state that the event is unicast, which means that it can have only one listener.

Supplying icons

Some of the beans that come with NetBeans are displayed on the palette with a cute icon. This makes life more pleasant for everyone. To supply an icon for the BeanInfo object we have been developing, we have it implement the getIcon() method. You can supply up to four icons, with sizes of 16 × 16 or 32 × 32, in color or monochrome. Here’s the getIcon() method for DialBeanInfo:

    public class DialBeanInfo extends SimpleBeanInfo {
      ...
      public java.awt.Image getIcon(int iconKind) {
      
        if (iconKind == BeanInfo.ICON_COLOR_16x16) {
          return loadImage("DialIconColor16.gif");
        } else
        if (iconKind == BeanInfo.ICON_COLOR_32x32) {
          return loadImage("DialIconColor32.gif");
        } else
        if (iconKind == BeanInfo.ICON_MONO_16x16) {
          return loadImage("DialIconMono16.gif");
        } else
        if (iconKind == BeanInfo.ICON_MONO_32x32) {
          return loadImage("DialIconMono32.gif");
        }
        return null;
      }

This method is called with a constant, indicating what kind of icon is being requested; for example, BeanInfo.ICON_COLOR_16x16 requests a 16 × 16 color image. If an appropriate icon is available, it loads the image and returns an Image object. If the icon isn’t available, it returns null. For convenience, you can package the images in the same JAR file as the bean and its BeanInfo class.

Though we haven’t used them here, you can also use a BeanInfo object to provide information about other public methods of your bean (for example, array-valued properties) and other features.

Creating customizers and property editors

JavaBeans lets you provide a customizer for your beans. Customizers are objects that do advanced customization for a bean as a whole; they let you provide your own GUI for tweaking your bean. We won’t show you how to write a customizer; it’s not too difficult, but it’s beyond the scope of this chapter. Suffice it to say that a customizer must implement the java.beans.Customizer interface and should extend Component (or JComponent) so that it can be displayed.

Property editors are a way of giving the properties sheet additional capabilities. For example, you could supply a property editor to let you edit a property type that is specific to your bean. You could provide a property editor that would let you edit an object’s price in dollars and cents. We’ve already seen a couple of property editors: the editor used for Color-valued properties is fundamentally the same as a property editor you might write yourself. In addition, the Molecule bean uses a property editor to specify its moleculeName property. A property editor isn’t quite as fancy as a customizer, but describing it fully is also beyond the scope of this chapter.

Again, describing how to write a property editor is also beyond the scope of this chapter. However, it might help you to know that a property editor must implement the PropertyEditor interface; it usually does so by extending the PropertyEditorSupport class, which provides default implementations for most of the methods.

Handcoding with Beans

So far, we’ve seen how to create and use beans within a bean application builder environment. That is the primary motivation for JavaBeans, at least in GUI development. But beans are not limited to being used by automated tools. There’s no reason we can’t use beans in handwritten code. You could use a builder to assemble beans for the user interface of your application and then load that serialized bean or a collection of beans in your own code, just as NetBeans does when told to use object serialization. We’ll give an example of that in a moment.

Bean Instantiation and Type Management

Beans are an abstraction over simple Java classes. They add, by convention, features that are not part of the Java language. To enable certain additional capabilities of JavaBeans, we use special tools that take the place of basic language operations. Specifically, when working with beans, we are provided with replacements for three basic Java operations: creating an object with new, checking the type of an object with the instanceof operator, and casting a type with a cast expression. In place of these, use the corresponding static methods of the java.beans.Beans class, shown in Table 22-1.

Table 22-1. Methods of the java.beans.Beans class

Operator

Equivalent

New

Beans.instantiate(classloader, name)

Instanceof

Beans.isInstanceOf(object, class)

Beans.instantiate() is the new operation for beans. It takes a class loader and the name of a bean class or serialized bean as arguments. Its advantage over the plain new operator is that it can also load beans from a serialized form. If you use instantiate(), you don’t have to specify in advance whether you will provide the bean as a class or as a serialized object. The instantiate() method first tries to load a resource file based on the name bean, by turning package-style names (with dots) into a path-style name with slashes and then appending the suffix .ser. For example, magicbeans.NumericField becomes magicbeans/NumericField.ser. If the serialized form of the bean is not found, the instantiate() method attempts to create an instance of the class by name.[47]

Beans.isInstanceOf() and Beans.getInstanceOf() do the jobs of checking a bean’s type and casting it to a new type. These methods were intended to allow one or more beans to work together to implement “virtual” or dynamic types. They are supposed to allow beans to take control of this behavior, providing different “views” of themselves. However, they currently don’t add any functionality and aren’t widely used.

Working with Serialized Beans

Remember the Juggler we serialized a while back? Well, it’s time to revive him, just like Han Solo from his “Carbonite” tomb in Star Wars. We’ll assume that you saved the Juggler by flipping on the Serialization property while working with the LearnJava1 class and that NetBeans, therefore, saved him in the file LearnJava1_juggler1.ser. If you didn’t do this, you can use the following snippet of code to serialize the bean to a file of your choice:

    // Serialize a Juggler instance to a file...
    import magicbeans.sunw.demo.juggler.Juggler;
    import java.io.*;
     
    public class SerializeJuggler {
       public static void main( String [] args ) throws Exception
       {
          Juggler duke = new Juggler();
          ObjectOutputStream oout = new ObjectOutputStream(
             new FileOutputStream("juggler.ser") );
          oout.writeObject( duke );
          oout.close();
       }
    }

Once you have the frozen Juggler, compile the following small application:

    //file: BackFromTheDead.java
    import java.awt.Component;
    import javax.swing.*;
    import java.beans.*;
      
    public class BackFromTheDead extends JFrame {
      
      public BackFromTheDead( String name ) {
        super("Revived Beans!");
        try {
          Object bean = Beans.instantiate(
            getClass().getClassLoader(), name );
      
          if ( Beans.isInstanceOf( bean, JComponent.class) ) {
            JComponent comp = (JComponent)
              Beans.getInstanceOf(bean, JComponent.class);
            getContentPane().add("Center", comp);
          } else {
              System.out.println("Bean is not a JComponent...");
          }
        } catch ( java.io.IOException e1 ) {
          System.out.println("Error loading the serialized object");
        } catch ( ClassNotFoundException e2 ) {
          System.out.println(
             "Can't find the class that goes with the object");
        }
      }
      
      public static void main(String [] args) {
        JFrame frame = new BackFromTheDead( args[0] );
        frame.pack();
        frame.setVisible(true);
      }
    }

Run this program, passing the name of your serialized object as an argument and making sure that our magicbeans.jar file is in your classpath. The name should not include the .ser extension in the name; the Beans.instantiate() method adds this automatically in its search for the serialized or class version. The juggler should spring back to life, juggling once again as shown in Figure 22-9.

The restored Juggler
Figure 22-9. The restored Juggler

In BackFromTheDead, we use Beans.instantiate() to load our serialized bean by name. We then check to see whether it is a GUI component using Beans.isInstanceOf(). (It is, because the Juggler is a subclass of java.awt.Component.) Finally, we cast the instantiated object to a Component with Beans.getInstanceOf() and add it to our application’s JFrame. Notice that we still need a static Java cast to turn the Object returned by getInstanceOf() into a JComponent. This cast may seem gratuitous, but it is the bridge between the dynamic beans lookup of the type and the static, compile-time view of the type.

Everything we’ve done here could be done using the plain java.io.ObjectInputStream discussed in Chapter 12. But these bean management methods are intended to shield the user from details of how the beans are implemented and stored.

One more thing before we move on. We blithely noted that when the Juggler was restored, the bean began juggling again. This implies that threads were started when the bean was deserialized. Serialization doesn’t automatically manage transient resources such as threads or even loaded images, but it’s easy to take control of the process to finish reconstructing the bean’s state when it is deserialized. Have a look at the Juggler source code (provided with the examples) and refer to Chapter 12 for a discussion of object deserialization using the readObject() method.

Runtime Event Hookups with Reflection

We’ve discussed reflection largely in terms of how design tools use it to analyze classes. Today, reflection is frequently finding its way into applications to perform dynamic activities that wouldn’t be possible otherwise. In this section, we’ll look at a dynamic event adapter that can be configured at runtime.

In Chapter 16, we saw how adapter classes could be built to connect event firings to arbitrary methods in our code, allowing us to cleanly separate GUI and logic in our applications. In this chapter, we have seen how NetBeans interposes this adapter code between beans to do this for us.

The AWT/Swing event model reduces the need to subclass components to perform simple hookups. If we start relying heavily on special adapter classes, we can quickly end up with as many adapters as components. Anonymous inner classes let us hide these classes, but they’re still there. A potential solution for large or specialized applications is to create generic event adapters that serve a number of event sources and targets simultaneously.

The java.beans.EventHandler is a dynamic event dispatcher that simply calls methods in response to events. What makes the EventHandler unusual in Java is that it is the first standard utility to use reflection to allow us to specify the method by name. In other words, you ask the EventHandler to direct events to a handler by specifying the handler object and the string name of the method to invoke on that object.

We can use the create() method of EventHandler to get an adapter for a specified type of event listener, specifying a target object and method name to call when that event occurs. The target object doesn’t have to be a listener for the particular event type or any other particular kind of object. The following application, DynamicHookup, uses the EventHandler to connect a button to a launchTheMissiles() method in our class:

    //file: DynamicHookup.java
    import javax.swing.*;
    import java.awt.event.*;
    import java.beans.EventHandler;

    public class DynamicHookup extends JFrame {
      JLabel label = new JLabel( "Ready...", JLabel.CENTER );
      int count;

      public DynamicHookup() {
        JButton launchButton = new JButton("Launch!");
        getContentPane().add( launchButton, "South" );
        getContentPane().add( label, "Center" );
            launchButton.addActionListener(
                    (ActionListener)EventHandler.create(
                            ActionListener.class, this, "launchTheMissiles"));
      }
      public void launchTheMissiles() {
        label.setText("Launched: "+ count++ );
      }

      public static void main(String[] args) {
        JFrame frame = new DynamicHookup();
            frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.setSize(150, 150);
        frame.setVisible( true );
      }
    }

Here, we call the EventHandler’s create() method, passing it the ActionListener class, the target object (this), and a string with the name of the method to invoke on the target when the event arrives. EventHandler internally creates a listener of the appropriate type and registers our target information. Not only do we eliminate an inner class, but the implementation of EventHandler may allow it to share adapters internally, producing very few objects.

This example shows how we would call a method that takes no arguments—but the EventHandler can actually do more, setting JavaBeans properties in response to events. The following form of create() tells EventHandler to call the launchTheMissiles() method, passing the source property of the ActionEvent as an argument:

    EventHandler.create(
       ActionListener.class, target, "launchTheMissiles", "source")

All events have a source property (via the getSource() method), but we can go further, specifying a chain of property “gets” separated by dots, which are applied before the value is passed to the method. For example:

    EventHandler.create(
       ActionListener.class, target, "launchTheMissiles", "source.text")

The source.text parameter causes the value getSource().getText() to be passed as an argument to launchTheMissiles(). In our case, that would be the label of our button. Other forms of create() allow more flexibility in selecting which methods of a multimethod listener interface are used as well as other options. We won’t cover every detail of the tool here.

How it works

The EventHandler uses the java.lang.reflect.Proxy, which is a factory that can generate adapters implementing any type of interface at runtime. By specifying one or more event listener interfaces (e.g., ActionListener), we get an adapter that implements those listener interfaces generated for us on the fly. The adapter is a specially created class that delegates all the method calls on its interfaces to a designated InvocationHandler object. See Chapter 1 for more information about proxy classes.

BeanContext and BeanContextServices

So far we’ve talked about some sophisticated mechanisms for connecting Java beans together at design time and runtime. However, we haven’t talked at all about the environment in which Java beans live. To build advanced, extensible applications, we’d like a way for Java beans to find each other or “rendezvous” at runtime. The java.beans.beancontext package provides this kind of container environment. It also provides a generic “services” lookup mechanism for beans that wish to advertise their capabilities. These mechanisms have existed for some time, but they haven’t found much use in the standard Java packages. Still, they are interesting and important facilities that you can use in your own applications.

You can find a full explanation and example of how to use the bean context to find beans and listen for services in the expanded material on this book’s website.

The Java Activation Framework

The Java Activation Framework (JAF) can be used by beans that work with many external data types, such as media retrieved from files and streams. It is essentially a generalized content/protocol handler mechanism for JavaBeans. The javax.activation package contains an extensible set of classes that wrap arbitrary, raw data sources to provide access to their data as streams or objects, identify the MIME type of the data, and enumerate a registered set of “commands” for operating on the data.

The JAF provides two primary interfaces: DataSource and DataHandler. The DataSource acts like the protocol handlers we discussed in Chapter 14. It wraps the data source and determines a MIME type for the data stream. The DataHandler acts like a content handler, except it provides a great deal more than access to the data. A DataHandler is constructed to wrap a DataSource and interpret the data in different forms. It also provides a list of command operations that can be used to access the data. DataHandler also implements the java.awt.datatransfer.Transferable interface, allowing data to be passed among application components in a well-defined way.

Enterprise JavaBeans and POJO-Based Enterprise Frameworks

Enterprise JavaBeans (EJB) is a very big topic, and we can’t do more than provide a few paragraphs of insight here. If you want more information, see Enterprise JavaBeans by Richard Monson-Haefel (O’Reilly). The thrust of EJB takes the JavaBeans philosophy of portable, pluggable components and extends it to the server side to accommodate the sorts of things that multitiered, networked, and database-centric applications require. Although EJB pays homage to the basic JavaBeans concepts, it is much larger and more specialized. It doesn’t have a lot in common with the kinds of things we’ve been talking about in this chapter. EJBs are server-side components for networked applications. EJBs and plain Java beans are both reusable, portable components that can be deployed and configured for specific environments. But in the case of EJBs, the components encapsulate access to business logic and database tables instead of GUI and program elements.

EJB ties together a number of other Java enterprise-oriented APIs—including database access, transactions, and name services—into a single component model for server applications. EJB imposes a lot more structure on how you write code than plain-old Java beans. It does so to allow the server-side EJB container to take on a lot of responsibility and optimize your application’s activities without your having to write a lot of code.

The first two major releases of Java Enterprise Edition, which include EJBs, were considered by many to be overly complicated. Many classes, interfaces, and configuration files were required to support EJBs. As a result, a number of popular open source frameworks that make use of Plain Old Java Objects (POJOs) to accomplish the same tasks quickly rose to prominence. POJOs are Java objects that are not required to follow any convention, implement any interface, or inherit from any base class, although in practice they are often JavaBeans. The most notable of the POJO-based frameworks are Hibernate, a framework for mapping Java object state to a database, and Spring, a general-purpose enterprise application development framework.



[45] As of this writing, Sun’s Molecule example has some problems when used in NetBeans. Selecting a molecule type other than the default causes a compile-time error. You can use the Preview Design button on the NetBeans form editor to try the other molecule types.

[46] A Timer bean used to come with the NetBeans distribution but disappeared in version 4.0, so we’ve added our own replacement. We won’t discuss it here, but the source code is with the other bean examples and there is nothing special that isn’t covered elsewhere.

[47] This feature would seemingly be applicable to XML-serialized Java beans using the XMLOutputStream as well, but it is not currently implemented for them. This is another sign that the JavaBeans APIs have stagnated.