Turn Java classes into JavaBeans

Reuse your existing Java classes as JavaBeans components

Like many Java programmers, you've invested a lot of time and effort into your existing Java classes. You feel rightly proud of what you've accomplished. True, some of your classes may have been written for JDK 1.0.2, or even earlier, but they still run just fine, thank you very much. Wouldn't it be great if you could dust off those old applets and classes and repackage them as shiny new JavaBeans? Well, the good news is, you can. While some of the JavaBeans Specification depends on JDK 1.1 functionality, class files written to JDK 1.0.2 can still be modified to run as beans.

Beanify your applet

We're going to learn to "beanify" an applet by example. The applet we're going to beanify, ColorFadeBar, produces a title bar (perhaps for a Web page), with a color gradient, like this:

Figure 1: ColorFadeBar applet in action

You can see the full source code for this applet here. You may want to open another browser window (or print the applet) so you can follow along with this discussion.

Task 1: Identify your properties

The first task in beanifying an existing class (whether that class is an applet or not) is to identify what attributes of the class can be considered properties. (See my previous article on customization in the Resources below.) Properties allow the user of a class to customize how the class appears or behaves. For example, Figure 2 shows some attributes of the ColorFadeBar applet that are programmable (via the <PARAM> tags within an <APPLET> tag in HTML).

Figure 2: Programmable attributes of a ColorFadeBar

The font, font size, color, and alignment of the text message are all parameterized, as are the beginning and ending colors for the cool background fade effect, and the width and height of the applet. There are also two parameters (X0 and DY, not shown here; see Table 1 below) that allow you to nudge the text vertically or horizontally for various purposes.

These attributes of the applet aren't properties yet. A JavaBeans property consists of methods that allow the retrieval and/or modification of some internal state of a class. The applet currently doesn't have methods that provide that functionality.

Although applet parameters are often directly translatable to properties (since their purpose usually is to affect the appearance or behavior of an object), they are fundamentally different mechanisms. An applet accesses a parameter by calling java.applet.Applet.getParameter(), and then converting whatever string is returned to the appropriate type. A property, on the other hand, consists of a method or methods that the class exposes (that is, makes publicly available) in order to allow external agents to access encapsulated information.

If you used parameters while writing your applet, you were probably already thinking in terms of properties. In fact, the parameters to your applet are your first candidates for the properties of your new bean. Our ColorFadeBar applet has the following parameters:

WIDTHThe width of the applet
HEIGHTThe height of the applet
STARTCOLORThe beginning color for the background fade
ENDCOLORThe ending color for the background fade
TEXTCOLORThe color in which to render the message
TEXTThe message text
FADEDIRBackground fade direction (left, right, up, down)
TEXTDIRText alignment (left, center, right)
FONTThe name of the font for TEXT
FONTSIZEThe size of the font for TEXT

Text left or right margin offset from applet edge

(depending on TEXTDIR; default 5)

DYText baseline offset (default 0)
Table 1. Parameters to existing applet

These parameters can be used to customize how the applet works. We first need to identify what the properties of the new bean will be, and then add accessor functions for them. Table 2 shows the properties I've chosen for the new bean, a description of each property, and the parameter or parameters to which the property corresponds.

Property nameTypeDescriptionParameter(s)
HeightintHeight of the appletHEIGHT
WidthintWidth of the appletWIDTH
MessageStringThe message to displayTEXT
MessageFontFontThe font of the messageFONT, FONTSIZE
TextDirectionintThe text alignmentTEXTDIR
MessageColorColorThe color of the textTEXTCOLOR
ColorFromColorThe color at which fade beginsSTARTCOLOR
ColorToColorThe color at which fade endsENDCOLOR
FadeDirectionintThe direction in which color fadesFADEDIR
Table 2. Properties of the new JavaBean

Notice that some of the property names differ from their corresponding parameter names. There is no programmatic relationship between parameters and properties. In practice, it's probably best to give properties the same name as their corresponding parameters, but here I've changed them to demonstrate that they're entirely independent from parameters. Also, notice that one new property we're going to add, MessageFont, corresponds to more than one applet parameter. Another difference between parameters and properties is that applet parameters are all strings. It's frequently necessary to convert many of these properties from their string representations to some other type -- for example (in the ColorFadeBar source code):

    protected int ixGetParameter(String sName, int iDefault)
        int i;
        try {
       // Conversion from string to int occurs here
            i = Integer.parseInt(getParameter(sName), 16);
        catch (NumberFormatException e) { i = iDefault; }
        return i;
       // Conversion from int to Color occurs here
        if ((i = ixGetParameter("TEXTCOLOR", 0xffffff)) >= 0)
            _colorText = new Color(i);

In the JavaBean we're about to write, the MessageColor property will be accessible as type Color: No translation is necessary!

If the class you're turning into a bean isn't an applet (and therefore doesn't have parameters), don't worry. You can still examine the class and imagine what attributes you'd like to be able to customize if the class were a bean. For example, a class that accesses a database and returns a list of tables in the database is much more reusable if the name and location of the database can be configured by calling property accessors.

Once you've identified what properties your bean should have, the next step is to actually create the properties.

Task 2: Create bean properties

Now that we've identified the properties of our new bean (we've begun to define the Application Programming Interface, or API), we need to write code that makes the class a bean.

Here we come to a fundamental decision point. There are two options: Either we modify the existing class, which is possible if we have the source code, or we subclass the existing class (or applet) and add Bean functionality that way. I've taken the second approach for a few reasons:

  • Compatibility. Many applets are only Java 1.0.x compatible. Modifying the class to use Java 1.1+ features can cause problems if the applet is in use elsewhere. If you're operating in a totally Java-1.1 environment where you're sure your classes are operating in a Java 1.1 interpreter, compatibility probably won't be an issue for you.

  • Clarity. It's much easier to see what functionality is bean-related if you encapsulate all of the bean functionality in a separate subclass. You may or may not care about this for your application.

  • Availability of source code. If source code is unavailable, subclassing is your only alternative. There's a problem though: If you don't have the source code, you may not know the names of the protected variables you might need to make the set/get methods work. In this case, you might try a decompiler (assuming, of course, that you're not violating any license agreements) and guessing at what the field names mean, or experimenting with the decompiled code.

So, now we've decided to subclass ColorFadeBar to create the new ColorFadeBean. We create properties by adding accessor methods for each of the properties. Note that we've followed the naming conventions (unfortunately called design patterns by Sun) by naming property accessors void setProperty(Type param) and Type getProperty(). (That naming conventions are called design patterns by Sun is unfortunate because the phrase has an entirely different meaning elsewhere in the industry.) The Introspector class looks for signatures of this form in order to automatically identify properties of the class.

The property accessor methods that we've added to the class appear below:

    // Width property
    public void setWidth(int iWidth) { _iHpoints = iWidth;}
    public int getWidth() { return _iHpoints;}
    // Height property
    public void setHeight(int iHeight) { _iVpoints = iHeight; }
    public int getHeight() { return _iVpoints; }
    // Message property
    public void setMessage(String sText) {        _sString = sText;    }
    public String getMessage() { return _sString; }
    // Color From property
    public void setColorFrom(Color newColor) { _colorFrom = newColor;}
    public Color getColorFrom() { return _colorFrom;}
    // ColorTo property
    public void setColorTo(Color newColor) { _colorTo = newColor;}
    public Color getColorTo() { return _colorTo;}
    // Message font property
    public void setMessageFont(Font font) {
        if (font == null) { font = new Font("Helvetica", Font.BOLD, 12); }
        _messageFont = font;
    public Font getMessageFont() { return _messageFont;}
    // Message color
    public void setMessageColor(Color color) { _colorText = color;}
    public Color getMessageColor() { return _colorText;}
    // Fade direction
    public void setFadeDirection(int iNewFadeDirection)
        // If new direction is out of range, ignore
        if (iNewFadeDirection >= 0 || iNewFadeDirection <= 4) {
            _iFadeDirection = iNewFadeDirection;
    public int getFadeDirection() { return _iFadeDirection;}
    // Text direction
    public void setTextDirection(int iNewTextDirection)
        // If new direction is out of range, throw
        // exception
        if (iNewTextDirection == LEFT || iNewTextDirection == RIGHT ||
            iNewTextDirection == CENTER) {
            _iTextDirection = iNewTextDirection;
    public int getTextDirection() { return _iTextDirection;}
    // Handle real-time resizes.
    public void setBounds(int x, int y, int width, int height) {

You see we've also added setBounds(), which allows the application developer to resize the applet visually. Figure 3 shows the ColorBarBean operating as a bean in the BeanBox. Notice that all of the properties we've defined appear as expected in the property sheet to the right.

Figure 3: Applet recycled as a JavaBean, with properties

Task 3: Add custom property editors

Our JavaBean already looks good, but we want to make it easier to use for the application developer. One way to do this is by adding custom property editors that present properties in a more easily readable fashion. (See my previous article on property editors in the Resources.)

Property editors are a complex topic, so we're going to add a simple type called a tagged property editor. Look at the properties FadeDirection and TextDirection in Figure 3 above. They're both integers, but if you look at the code (above), you'll see that those integers have meaning (left, right, and so on) that don't appear in the property sheet. The developer simply has to know which integer to type in. If an invalid integer is entered, the bean rejects the value but offers no assistance. (Try this: Download the JAR file for all of these examples from the Resources below.)

We can do better. The PropertyEditor interface allows us to take control of how individual properties, or any property of a particular type, are edited in a bean's container. We're going to tell the Introspector how to edit the two direction properties by creating a BeanInfo object that describes all of the bean's properties. The java.beans.BeanInfo interface defines a method called getPropertyDescriptors(), which returns an array of PropertyDescriptor objects. Each PropertyDescriptor object describes one property of the bean to which the BeanInfo corresponds.

We derive the ColorFadeBeanBeanInfo class from java.beans.SimpleBeanInfo, a convenience class that implements the entire BeanInfo with do-nothing methods. That way, a programmer can override only the methods needed for a desired result and not have to implement the entire BeanInfo interface.

The ColorFadeBeanBeanInfo class source code looks like this:

1 2 3 Page 1
Page 1 of 3