You are on page 1of 19

1

JavaBeans
JavaBeans™ is a portable, platform-independent component
model written in the Java programming language. The JavaBeans
architecture was built through a collaborative industry effort and
enables developers to write reusable components in the Java
programming language.

With the JavaBeans API you can create reusable, platform-


independent components. Using JavaBeans-compliant application
builder tools, you can combine these components into applets,
applications, or composite components.

JavaBean components are known as beans. Beans are dynamic


in that they can be changed or customized. Through the design mode
of a builder tool, you use the property sheet or bean customizer to
customize the bean and then save (persist) your customized beans.

JavaBeans Concepts
The JavaBeans™ architecture is based on a component model
which enables developers to create software units called components.
Components are self-contained, reusable software units that can be
visually assembled into composite components, applets, applications,
and servlets using visual application builder tools. JavaBean
components are known as beans.

A set of APIs describes a component model for a particular


language. The JavaBeans API specificationdescribes the core detailed
elaboration for the JavaBeans component architecture.
Beans are dynamic in that they can be changed or customized.
Through the design mode of a builder tool you can use the Properties
window of the bean to customize the bean and then save (persist)
your beans using visual manupulation. You can select a bean from the
toolbox, drop it into a form, modify its appearance and behavior, define
its interaction with other beans, and combine it and other beans into
an applet, application, or a new bean.

The following list briefly describes key bean concepts.

• Builder tools discover a bean's features (that is, its properties,


methods, and events) by a process known as introspection.
Beans support introspection in two ways:

o By adhering to specific rules, known as design patterns,


when naming bean features. The Introspector class
examines beans for these design patterns to discover bean

1
2

features. The Introspector class relies on the core reflection


API. The trail The Reflection API is an excellent place to
learn about reflection.
o By explicitly providing property, method, and event
information with a related bean information class. A bean
information class implements the BeanInfo interface. A
BeanInfo class explicitly lists those bean features that are to
be exposed to application builder tools.

• Properties are the appearance and behavior characteristics of a


bean that can be changed at design time. Builder tools introspect
on a bean to discover its properties and expose those properties
for manipulation.

• Beans expose properties so they can be customized at design


time. Customization is supported in two ways: by using property
editors, or by using more sophisticated bean customizers.

• Beans use events to communicate with other beans. A bean that


is to receive events (a listener bean) registers with the bean that
fires the event (a source bean). Builder tools can examine a
bean and determine which events that bean can fire (send) and
which it can handle (receive).

• Persistence enables beans to save and restore their state. After


changing a bean's properties, you can save the state of the bean
and restore that bean at a later time with the property changes
intact. The JavaBeans architecture uses Java Object Serialization
to support persistence.

• A bean's methods are no different from Java methods, and can


be called from other beans or a scripting environment. By default
all public methods are exported.

Beans vary in functionality and purpose. You have probably met some
of the following beans in your programming practice:

• GUI (graphical user interface)

• Non-visual beans, such as a spelling checker

• Animation applet

• Spreadsheet application

2
3

Writing a Simple Bean


In this section you will learn more about beans by performing the
following actions:
• Creating a simple bean

• Compiling the bean

• Generating a Java Archive (JAR) file

• Loading the bean into the GUI Builder of the NetBeans


IDE

• Inspecting the bean's properties and events

Your bean will be named SimpleBean. Here are the steps to create it:

1.Write the SimpleBean code. Put it in a file named


SimpleBean.java, in the directory of your choice. Here's the
code:
import java.awt.Color;
import java.beans.XMLDecoder;
import javax.swing.JLabel;
import java.io.Serializable;

public class SimpleBean extends JLabel


implements Serializable {
public SimpleBean() {
setText( "Hello world!" );
setOpaque( true );
setBackground( Color.RED );
setForeground( Color.YELLOW );
setVerticalAlignment( CENTER );
setHorizontalAlignment( CENTER );
}
}
SimpleBean extends the javax.swing.JLabel graphic component and
inherits its properties, which makes the SimpleBean a visual
component. SimpleBean also implements the java.io.Serializable
interface. Your bean may implement either the Serializable or the
Externalizable interface.
2. Create a manifest, the JAR file, and the class file
SimpleBean.class. Use the Apache Ant tool to create these files.
Apache Ant is a Java-based build tool that enables you to generate
XML-based configurations files as follows:
<?xml version="1.0" encoding="ISO-8859-1"?>

<project default="build">

3
4

<dirname property="basedir" file="${ant.file}"/>

<property name="beanname" value="SimpleBean"/>


<property name="jarfile" value="${basedir}/${beanname}.jar"/>

<target name="build" depends="compile">


<jar destfile="${jarfile}" basedir="${basedir}" includes="*.class">
<manifest>
<section name="${beanname}.class">
<attribute name="Java-Bean" value="true"/>
</section>
</manifest>
</jar>
</target>

<target name="compile">
<javac destdir="${basedir}">
<src location="${basedir}"/>
</javac>
</target>

<target name="clean">
<delete file="${jarfile}">
<fileset dir="${basedir}" includes="*.class"/>
</delete>
</target>

</project>
It is recommended to save an XML script in the build.xml file,
because Ant recognizes this file name automatically.

3. Load the JAR file. Use the NetBeans IDE GUI Builder to load
the jar file as follows:

Start NetBeans.

From the File menu select "New Project" to create a new


application for your bean. You can use "Open Project" to add
your bean to an existing application.

Create a new application using the New Project Wizard.

Select a newly created project in the List of Projects, expand


the Source Packages node, and select the Default Package
element.

Click the right mouse button and select New|JFrameForm


from the pop-up menu.

4
5

Select the newly created Form node in the Project Tree. A


blank form opens in the GUI Builder view of an Editor tab.

Open the Palette Manager for Swing/AWT components by


selecting Palette Manager in the Tools menu.

In the Palette Manager window select the beans components


in the Palette tree and press the "Add from JAR" button.

Specify a location for your SimpleBean JAR file and follow the
Add from JAR Wizard instructions.

Select the Palette and Properties options from the Windows


menu.

Expand the beans group in the Palette window. The


SimpleBean object appears. Drag the SimpleBean object to
the GUI Builder panel.

The following figure represents the SimpleBean object loaded in the


GUI Builder panel:

5
6

4.Inspect Properties and Events. The SimpleBean properties will


appear in the Properties window. For example, you can change a
background property by selecting another color. To preview your
form, use the Preview Design button of the GUI Builder toolbar. To
inspect events associated with the SimpleBean object, switch to the
Events tab of the Properties window. You will learn more about bean
properties and events in the lessons that follow

Lesson: Properties
In the following sections you will learn how to implement bean
properties. A bean property is a named attribute of a bean that can
affect its behavior or appearance. Examples of bean properties include
color, label, font, font size, and display size.

The JavaBeans™ specification defines the following types of bean


properties:

• Simple – A bean property with a single value whose changes are


independent of changes in any other property.

• Indexed – A bean property that supports a range of values instead


of a single value.

• Bound – A bean property for which a change to the property results


in a notification being sent to some other bean.

• Constrained – A bean property for which a change to the property


results in validation by another bean. The other bean may reject
the change if it is not appropriate.

Bean properties can also be classified as follows:

• Writable – A bean property that can be changed

o Standard

o Expert

o Preferred

• Read Only – A bean property that cannot be changed.

• Hidden – A bean property that can be changed. However, these properties are not
disclosed with the BeanInfo class
BeanBuilder uses this schema to group and represent properties in the
Properties window.

6
7

Simple Properties
To add simple properties to a bean, add appropriate getXXX and setXXX
methods (or isXXX and setXXX methods for a boolean property).

The names of these methods follow specific rules called design


patterns. These design pattern-based method names allow builder
tools such as the NetBeans GUI Builder, to provide the following
features:

• Discover a bean's properties

• Determine the properties'


read/write attributes

• Determine the properties'


types

• Locate the appropriate


property editor for each
property type

• Display the properties


(usually in the Properties
window)

• Alter the properties (at


design time)

Bound Properties

Bound properties support the PropertyChangeListener (in the API reference


documentation) class.
Sometimes when a Bean property changes, another object might need
to be notified of the change, and react to the change.

Whenever a bound property changes, notification of the change is sent


to interested listeners.

The accessor methods for a bound property are defined in the same
way as those for simple properties. However, you also need to provide
the event listener registration methods forPropertyChangeListener classes
and fire a PropertyChangeEvent (in the API reference documentation)
event to the PropertyChangeListener objects by calling their propertyChange
methods

7
8

The convenience PropertyChangeSupport (in the API reference


documentation) class enables your bean to implement these methods.
Your bean can inherit changes from the PropertyChangeSupportclass, or
use it as an inner class.
In order to listen for property changes, an object must be able to add
and remove itself from the listener list on the bean containing the
bound property. It must also be able to respond to the event
notification method that signals a property change.

The PropertyChangeEvent class encapsulates property change information,


and is sent from the property change event source to each object in
the property change listener list with the propertyChange method.

Implementing Bound Property Support Within a Bean


To implement a bound property in your application, follow these steps:
1. Import the java.beans package. This gives you access to the
PropertyChangeSupport class.

2. Instantiate a PropertyChangeSupport object. This object maintains


the property change listener list and fires property change
events. You can also make your class a PropertyChangeSupport
subclass.

3. Implement methods to maintain the property change listener


list. Since a PropertyChangeSupport subclass implements these
methods, you merely wrap calls to the property-change support
object's methods.

4. Modify a property's set method to fire a property change event


when the property is changed.

Constrained Properties

A bean property is constrained if the bean supports the


VetoableChangeListener(in the API reference documentation) and
PropertyChangeEvent(in the API reference documentation) classes, and if
the set method for this property throws a PropertyVetoException(in the
API reference documentation).
Constrained properties are more complicated than bound properties
because they also support property change listeners which happen to
be vetoers.

8
9

The following operations in the setXXX method for the constrained


property must be implemented in this order:

1. Save the old value in case the change is vetoed.

2. Notify listeners of the new proposed value, allowing them to


veto the change.

3. If no listener vetoes the change (no exception is thrown), set


the property to the new value.

The accessor methods for a constrained property are defined in the


same way as those for simple properties, with the addition that the
setXXX method throws a PropertyVetoException exception. The syntax is as
follows:
public void setPropertyName(PropertyType pt)
throws PropertyVetoException {code}

Handling Vetoes
If a registered listener vetoes a proposed property change by throwing
a PropertyVetoException exception, the source bean with the constrained
property is responsible for the following actions:
• Catching exceptions.

• Reverting to the old value for the property.

• Issuing a new VetoableChangeListener.vetoableChange call to all


listeners to report the reversion.
The VetoableChangeListener class throws a PropertyVetoException and
handles the PropertyChangeEvent event fired by the bean with the
constrained property.
The VetoableChangeSupport provides the following operations:

• Keeping track of VetoableChangeListener objects.

• Issuing the vetoableChange method on all registered listeners.

• Catching any vetoes (exceptions) thrown by listeners.

• Informing all listeners of a veto by calling vetoableChange


again, but with the old property value as the proposed
"new" value.

9
10

Indexed Properties
An indexed property is an array of properties or objects that supports
a range of values and enables the accessor to specify an element of a
property to read or write.

Indexed properties are specified by the following methods:


//Methods to access individual values
public PropertyElement getPropertyName(int index)
public void setPropertyName(int index, PropertyElement element)
and
//Methods to access the entire indexed property array
public PropertyElement[] getPropertyName()
public void setPropertyName(PropertyElement element[])
Note that the distinction between the get and set methods for indexed
properties is subtle. The get method either has an argument that is the
array index of the property, or returns an array. The set method either
has two arguments, namely an integer array index and the property
element object that is being set, or has the entire array as an
argument.

Manipulating Events

Event passing is the means by which components communicate with


each other. Components broadcast events, and the underlying
framework delivers the events to the components that are to be
notified. The notified components usually perform some action based
on the event that took place.

The event model was designed to accommodate the JavaBeans™


architecture. To understand how events and event handling work in the
JavaBeans component model, you must understand the concepts of
events, listeners, and sources. To refresh your knowledge in these
areas, read the Writing Event Listeners lesson of the Swing tutorial.

The event model that is used by the JavaBeans architecture is a


delegation model. This model is composed of three main parts:
sources, events, and listeners.

The source of an event is the object that originates or fires the event.
The source must define the events it will fire, as well as the methods
for registering listeners of those events. A listener is an object that
indicates that it is to be notified of events of a particular type.
Listeners register for events using the methods defined by the sources
of those events.

10
11

From the Properties lesson you discovered two event listeners. The
PropertyChangeListener(in the API reference documentation) interface
provides a notification whenever a bound property value is changed
and the VetoableChangeListener(in the API reference documentation)
creates a notification whenever a bean changes a constrained property
value.
Simple Event Example
This example represents an application that performs an action when a
button is clicked. Button components are defined as sources of an
event type called ActionEvent(in the API reference documentation).
Listeners of events of this type must register for these events using
the addActionListener method.
Therefore, the addActionListener method is used to register the
ButtonHandler object as a listener of the ActionEvent event that is fired by
the button.

In addition, according to the requirements of the ActionListener class,


you must define an actionPerformed method, which is the method that is
called when the button is clicked.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JTextArea;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class ButtonHandler implements ActionListener {


/**
* Component that will contain messages about
* events generated.
*/
private JTextArea output;
/**
* Creates an ActionListener that will put messages in
* JTextArea everytime event received.
*/
public ButtonHandler( JTextArea output )
{
this.output = output;
}

/**
* When receives action event notification, appends
* message to the JTextArea passed into the constructor.
*/
public void actionPerformed( ActionEvent event )
{

11
12

this.output.append( "Action occurred: " + event + '\n' );


}
}

class ActionTester {
public static void main(String args[]) {
JFrame frame = new JFrame( "Button Handler" );
JTextArea area = new JTextArea( 6, 80 );
JButton button = new JButton( "Fire Event" );
button.addActionListener( new ButtonHandler( area ) );
frame.add( button, BorderLayout.NORTH );
frame.add( area, BorderLayout.CENTER );
frame.pack();
frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}

Bean Persistence
A bean has the property of persistence when its properties, fields, and
state information are saved to and retrieved from storage. Component
models provide a mechanism for persistence that enables the state of
components to be stored in a non-volatile place for later retrieval.

The mechanism that makes persistence possible is called serialization.


Object serialization means converting an object into a data stream and
writing it to storage. Any applet, application, or tool that uses that
bean can then "reconstitute" it by deserialization. The object is then
restored to its original state.

For example, a Java application can serialize a Frame window on a


Microsoft Windows machine, the serialized file can be sent with e-mail
to a Solaris machine, and then a Java application can restore the
Frame window to the exact state which existed on the Microsoft
Windows machine.

Any applet, application, or tool that uses that bean can then
"reconstitute" it by deserialization.

All beans must persist. To persist, your beans must support


serialization by implementing either the java.io.Serializable(in the API
reference documentation) interface, or the java.io.Externalizable(in the
API reference documentation) interface. These interfaces offer you the
choices of automatic serialization and customized serialization. If any

12
13

class in a class's inheritance hierarchy implements Serializable or


Externalizable, then that class is serializable.

Classes That Are Serializable


Any class is serializable as long as that class or a parent class
implements the java.io.Serializable interface. Examples of serializable
classes include Component, String, Date, Vector, and Hashtable. Thus, any
subclass of the Component class, including Applet, can be serialized.
Notable classes not supporting serialization include Image, Thread,
Socket, and InputStream. Attempting to serialize objects of these types
will result in an NotSerializableException.
The Java Object Serialization API automatically serializes most fields of
a Serializable object to the storage stream. This includes primitive
types, arrays,and strings. The API does not serialize or deserialize
fields that are marked transient or static.

Controlling Serialization
You can control the level of serialization that your beans undergo.
Three ways to control serilization are:

• Automatic serialization, implemented by the Serializable


interface. The Java serialization software serializes the
entire object, except transient and static fields.

• Customized serialization. Selectively exclude fields you do


not want serialized by marking with the transient (or static)
modifier.

• Customized file format, implemented by the Externalizable


interface and its two methods. Beans are written in a
specific file format.

Default Serialization: The Serializable Interface


The Serializable interface provides automatic serialization by using the
Java Object Serialization tools. Serializable declares no methods; it acts
as a marker, telling the Object Serialization tools that your bean class
is serializable. Marking your class Serializable means you are telling the
Java Virtual Machine (JVM) that you have made sure your class will
work with default serialization. Here are some important points about
working with the Serializable interface:

• Classes that implement Serializable must have an access to


a no-argument constructor of supertype. This constructor

13
14

will be called when an object is "reconstituted" from a .ser


file.

• You don't need to implement Serializable in your class if it


is already implemented in a superclass.

• All fields except static and transient fields are serialized.


Use the transient modifier to specify fields you do not want
serialized, and to specify classes that are not serializable.

The Externalizable Interface


Use the Externalizable interface when you need complete control over
your bean's serialization (for example, when writing and reading a
specific file format). To use the Externalizable interface you need to
implement two methods: readExternal and writeExternal. Classes that
implement Externalizable must have a no-argument constructor.

Introspection
Introspection is the automatic process of analyzing a bean's design
patterns to reveal the bean's properties, events, and methods. This
process controls the publishing and discovery of bean operations and
properties. This lesson explains the purpose of introspection,
introduces the Introspection API, and gives an example of
introspection code.

Purpose of Introspection
A growing number of Java object repository sites exist on the Internet
in answer to the demand for centralized deployment of applets,
classes, and source code in general. Any developer who has spent time
hunting through these sites for licensable Java code to incorporate into
a program has undoubtedly struggled with issues of how to quickly and
cleanly integrate code from one particular source into an application.

The way in which introspection is implemented provides great


advantages, including:

1. Portability - Everything is done in the Java platform, so


you can write components once, reuse them everywhere.
There are no extra specification files that need to be
maintained independently from your component code.
There are no platform-specific issues to contend with.
Your component is not tied to one component model or
one proprietary platform. You get all the advantages of

14
15

the evolving Java APIs, while maintaining the portability


of your components.

2. Reuse - By following the JavaBeans design conventions,


implementing the appropriate interfaces, and extending
the appropriate classes, you provide your component with
reuse potential that possibly exceeds your expectations.

Introspection API
The JavaBeans API architecture supplies a set of classes and interfaces
to provide introspection.
The BeanInfo (in the API reference documentation) interface of the
java.beans package defines a set of methods that allow bean
implementors to provide explicit information about their beans. By
specifying BeanInfo for a bean component, a developer can hide
methods, specify an icon for the toolbox, provide descriptive names for
properties, define which properties are bound properties, and much
more.
The getBeanInfo(beanName) (in the API reference documentation) of the
Introspector (in the API reference documentation) class can be used by
builder tools and other automated environments to provide detailed
information about a bean. The getBeanInfo method relies on the naming
conventions for the bean's properties, events, and methods. A call to
getBeanInfo results in the introspection process analyzing the bean’s
classes and superclasses.
The Introspector class provides descriptor classes with information about
properties, events, and methods of a bean. Methods of this class
locate any descriptor information that has been explicitly supplied by
the developer through BeanInfo classes. Then the Introspector class
applies the naming conventions to determine what properties the bean
has, the events to which it can listen, and those which it can send.

The following figure represents a hierarchy of the FeatureDescriptor


classes:

15
16

Each class represented in this group describes a particular attribute of


the bean. For example, the isBound method of the PropertyDescriptor class
indicates whether a PropertyChangeEvent event is fired when the value of
this property changes.
Bean Customization

Customization provides a means for modifying the appearance and


behavior of a bean within an application builder so it meets your
specific needs. There are several levels of customization available for a
bean developer to allow other developers to get maximum benefit
from a bean’s potential functionality.
The following links are useful for learning about property editors and
customizers:
• PropertyEditor(in the API reference documentation)
interface
• PropertyEditorSupport(in the API reference
documentation) class
• PropertyEditorManager(in the API reference
documentation) class
• Customizer(in the API reference documentation)
interface
• BeanInfo(in the API reference documentation)
interface
A bean's appearance and behavior can be customized at design time
within beans-compliant builder tools. There are two ways to customize
a bean:

16
17

• By using a property editor. Each bean property has its


own property editor. The NetBeans GUI Builder usually
displays a bean's property editors in the Properties
window. The property editor that is associated with a
particular property type edits that property type.

• By using customizers. Customizers give you complete


GUI control over bean customization. Customizers are
used where property editors are not practical or
applicable. Unlike a property editor, which is associated
with a property, a customizer is associated with a bean.

Property Editors
A property editor is a tool for customizing a particular property type.
Property editors are activated in the Properties window. This window
determines a property's type, searches for a relevant property editor,
and displays the property's current value in a relevant way.

Property editors must implement the PropertyEditor interface, which


provides methods to specify how a property should be displayed in a
property sheet. The following figure represents the Properties window
containing myBean1 properties:

You begin the process of editing these properties by clicking the


property entry. Clicking most of these entries will bring up separate
panels. For example, to set up the foreground or background use selection
boxes with choices of colors, or press the "..." button to work with a
standard ColorEditor window. Clicking on the toolTipText property opens
a StringEditor window.

The support class PropertyEditorSupport provides a default


implementation of the PropertyEditor interface. By subclassing your
property editor from PropertyEditorSupport, you can simply override the
methods you need.

To display the current property value "sample" within the Properties


window, you need to override isPaintable to return true. You then must
override paintValue to paint the current property value in a rectangle in
the property sheet. Here's how ColorEditor implements paintValue:
public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
Color oldColor = gfx.getColor();
gfx.setColor(Color.black);
gfx.drawRect(box.x, box.y, box.width-3, box.height-3);

17
18

gfx.setColor(color);
gfx.fillRect(box.x+1, box.y+1, box.width-4, box.height-4);
gfx.setColor(oldColor);
}
To support the custom property editor, override two more methods.
Override supportsCustomEditor to return true, and then override
getCustomEditor to return a custom editor instance.
ColorEditor.getCustomEditor returns this.

In addition, the PropertyEditorSupport class maintains a


PropertyChangeListener list, and fires property change event notifications
to those listeners when a bound property is changed.

How Property Editors are Associated with Properties


Property editors are discovered and associated with a given property in
the following ways:

• Explicit association by way of a BeanInfo object. The editor


of the title's property is set with the following line of
code:
• pd.setPropertyEditorClass(TitleEditor.class);

• Explicit registration by way of the


method. This
java.beans.PropertyEditorManager.registerEditor
method takes two arguments: the bean class type, and
the editor class to be associated with that type.

• Name search. If a class has no explicitly associated


property editor, then the PropertyEditorManager searchs for
that class's property editor in the following ways:

o Appending "Editor" to the fully qualified class name.


For example, for the my.package.ComplexNumber class,
the property editor manager would search for the
my.package.ComplexNumberEditor class.

o Appending "Editor" to the class name and searching


a class path.

Customizers
You have learned that builder tools provide support for you to create
your own property editors. What other needs should visual builders
meet for complex, industrial-strength beans? Often it is undesirable to
have all the properties of a bean revealed on a single (sometimes
huge) property sheet. What if one single root choice about the type of

18
19

the bean rendered half the properties irrelevant? The JavaBeans


specification provides for user-defined customizers, through which you
can define a higher level of customization for bean properties than is
available with property editors.

When you use a bean Customizer, you have complete control over how
to configure or edit a bean. A Customizer is an application that
specifically targets a bean's customization. Sometimes properties are
insufficient for representing a bean's configurable attributes.
Customizers are used where sophisticated instructions would be
needed to change a bean, and where property editors are too primitive
to achieve bean customization.

All customizers must:

• Extend java.awt.Component or one of its subclasses.

• Implement the java.beans.Customizer interface This means


implementing methods to register PropertyChangeListener
objects, and firing property change events at those
listeners when a change to the target bean has occurred.

• Implement a default constructor.

• Associate the customizer with its target class via


BeanInfo.getBeanDescriptor.

19

You might also like