Reflecting, introspecting, and customizing JavaBeans
The Sun JDK JavaBeans API provides a framework for defining reusable software components that can be manipulated in a visual builder tool. You may have already read the developerWorks tutorial Designing JavaBeans for visual programming. This article extends your design so that visual builder tools can use reflection, introspection, or both to analyze JavaBeans and consequently to allow users to customize them. It includes an example showing how to add your beans to WebSphere AppletDesigner, where users can customize or manipulate the beans from within the tool itself using property editors or customizers you design.
JavaBeans are designed to have properties. These properties are attributes or characteristics that define the behavior or state of an object. Properties are referenced by a name and can be of any type. For example, image name is an attribute of an
image bean . The
image bean might also have a property like
backgroundColor . These properties are usually exposed to a user in a visual builder so that they can be changed or customized.
Before you start developing ways for users to customize your beans, you should understand the reflection technology introduced in JDK 1.1. Reflection is the process of looking at a JavaBean during run time in order to understand its features or properties. A visual builder can read the internals of a JavaBean from its binary class file using the Java Reflection APIs. It can interpret the bean’s properties using a convention known as design patterns. You should use design patterns, or templates, when you name setters and getters for properties.
Setters are a type of method that assign a value to a property. Getters are a type of method that allow a program to retrieve the current value of a property. The method name is based on the property contained in the bean.
As an example, a clock bean needs to have its style, analog or digital, set. Its setter method would begin with the word
set and its getter method would begin with
get . The method should have the name of the property contained within the method name itself. For example, the style property methods would be named setStyle() and getStyle(). If you wanted to allow users or tools to manipulate the background color of the clock, the bean would have the accessor methods setBackgroundColor() and getBackgroundColor().
You can choose to not make public the setter and getter methods for a bean’s property. In that case, the property is known as a read-only or write-only property where users don’t have the authority to customize it.
Reflection also allows a user or tool to manipulate a bean. The reflection process can occur by looking at the bean code itself programmatically or by introspecting BeanInfo. (See Introspection.) Reflection is an example of a low-level interface.
Take a look at an example demonstrating reflection. In the example, text is a property of the TickerTape bean. You will see a method to both retrieve and set the value of the text property. The last statement in the setText() method fires an event to make the visual builder aware that a change with the bean has occurred.
Customization using property sheets and editors
Customization gives users the ability to visually modify a bean’s properties to meet their needs.
After you design your beans so that reflection and introspection can occur, you should test your code to verify that it actually works. The ability to customize on the user level is a vital part of the bean anatomy. For example, imagine you have a clock part. A user should have the ability to customize it with such properties as format (digital or analog) or time zone. A bean like this should use design properties or a BeanInfo class to allow these properties to be retrieved and set.
Visual builders use property sheets to allow users to make property changes. A property sheet displays a list of the properties associated with a bean. An example of a property sheet is shown in Figure 1.
This property sheet comes from the AppletDesigner visual builder tool in the IBM WebSphere Studio tool suite.
AppletDesigner allows you to create applets, applications, and JavaBeans by placing beans on a visual layout and connecting them to create events. Properties are listed in the first column and values are listed in the second column. You can modify the property values by selecting the second column. Depending on the property you select, either a drop-down list or a separate window appears.
Each property listed should have a property editor associated with it. A property editor is a class that allows you to edit the property of a bean visually. Java provides property editors for primitive data types such as Boolean and Color. You need to code property editors for more complicated properties such as the
first picture property listed in the property sheet above. A class called
FileNameEditor was developed to handle modification to the
first picture property.
All property editors must implement the java.beans.PropertyEditor interface. The easiest way to create a simple PropertyEditor is to extend the java.beans.PropertyEditorSupport class that implements java.beans.PropertyEditor.
Look at a portion of the FileNameEditor class code. This sample code generates the Figure 2.
To test the properties of the bean that you just designed, add the bean to the AppletDesigner tool by adding your bean to the tool’s Palette. To add the bean to the Palette:
- Select Add from the Palette pop-up menu. A dialog appears where you enter the name of the jar file that contains the JavaBean.
- Select the category you want to add the bean to.
- Click Add to add the bean.
In AppletDesigner, you select beans from the palette and drop them on the Composer window. The Composer window is used to design applets or applications consisting of JavaBeans. Select the bean you just added and drop it on the Composer window. You should see the properties displayed in the property sheet. If your properties do not appear in the property sheet or if the correct values do not appear on the right side, check how you coded your BeanInfo or your property editor. If everything appears accurately, users can customize your bean to their liking.
Customization using customizers
Alternatively, for more sophisticated beans, the JavaBeans API has defined a customizer interface that behaves like a wizard. Wizards are graphical user interfaces that step you through a process, in this case, the process of users configuring beans. Most visual builders provide customizers for their more complicated beans. An example of a customizer from the AppletDesigner tool appears in Figure 3.
Like property editors, customizers are associated with their beans using the BeanInfo class. The BeanInfo method
getBeanDescriptor() returns a
BeanDescriptor that contains the bean’s class and the bean’s customizer class if it exists. All bean customizers must implement the
java.beans.Customizer interface and extend the
You can see a portion of the code that implements the customizer shown in Figure 3.
Not all properties have to be implemented in the customizer. Usually, the more complicated properties are defined within the customizer. AppletDesigner ties the customizer to a bean on the Composer window. As a user customizes a bean’s properties, the changes take effect dynamically. If the user cancels the customization, the bean should be reset to its initial state. If you created a customizer with your bean, you can view it by clicking Customizer on the Property Sheet in the AppletDesigner tool.
Reflection, introspection, and customization are somewhat dependent on each other. Visual builders need to expose a bean’s properties to the users so that they can customize the properties. A tool or program must be able to introspect before it can allow a user to customize its beans. Therefore, you should provide a BeanInfo with references to default property editors or customized property editors.
You don’t have to be writing an IDE or visual builder to make use of the reflection and introspection classes. They are also useful if you need to find out about third-party beans. You can develop an application that examines beans and determines their use on the fly to do whatever you want with them. Designing beans with customization is very important for developers who want to get their beans out the door. Users must be able to manipulate the beans that they buy, beg, borrow, or steal. You can easily make this possible by implementing a BeanInfo, property editors, and customizers for your beans.
Learn more about the JavaBeans component APIs for Java.