Sei sulla pagina 1di 24

JavaBeans

Seminar Report
Antoniol, Sandro, TIE04

FHNW
Hochschule f
ur Technik
Studiengang I
Supervisor:
Prof. Dr. Dominik Gruntz

Windisch, April 9, 2007

Abstract
This report has been written as a part of the seminar Enterprise Computing assignment. The aim of this report is to make a detailed examination of JavaBeans, a
component model in the Java world. After giving a brief overview of what JavaBeans
are and what they can be used for, we will look at the concepts of JavaBeans. This
includes, but is not limited to: properties, events and methods, introspection, long term
persistence, and BeanContexts. Samples are given to facilitate the comprehension of the
topics. To avoid showing only loose code snippets with no or only little relation to each
other, a FontSelector JavaBean will be developed step by step through this report. The
resulting Bean allows selecting conveniently a font and setting the font-size. Image 1
depicts the final product.

Figure 1: The FontSelector JavaBean


Please note, that this report is target to experienced programmers. Keywords such as
observer pattern, serialization, AWT, Swing and reflection should be known by you.

Seminar Report

Contents
1. Introduction to JavaBeans
1.1. Definition of a software component
1.2. Definition of a builder tool . . . . .
1.3. JavaBeans at a glance . . . . . . .
1.4. JavaBeans basic rules . . . . . . .
2. Beans Architecture
2.1. Properties . . . . . . .
2.2. Simple Properties . . .
2.3. Indexed Properties . .
2.4. Bound Properties . . .
2.5. Constrained Properties

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.

4
4
4
5
6

.
.
.
.
.

6
6
7
7
8
9

3. Events and Methods


11
3.1. Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4. Instrospection
4.1. Methods of the BeanInfo class . . . . . . . . .
4.1.1. Events . . . . . . . . . . . . . . . . . .
4.1.2. Properties . . . . . . . . . . . . . . . .
4.1.3. Method . . . . . . . . . . . . . . . . .
4.2. Personalized Bean information with BeanInfo

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

13
13
13
13
13
14

5. Persistence
15
5.1. Long-term persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2. Bean Reconstitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6. BeanContext

16

7. The Beans class

17

8. Conclusion

18

9. References

19

A. Sample BeanContext applicaton

20

Sandro Antoniol

Page 3/24

Seminar Report

1. Introduction to JavaBeans
To start with I would like to quote a sentence from the official JavaBeans API specification, which gives a first definition of what JavaBeans are:
A JavaBean is a reusable software component that can be manipulated visually in a builder tool.
Even though this quote seams to be quite simple, we have to clarify what is meant
by software component and builder tool in order to be able to fully understand the
quotes statement.

1.1. Definition of a software component


Software components are self-contained software units developed according to the motto
Developed them once, run and reused them everywhere. Or in other words, reusability
is the main concern behind the component model. Software components offer predefined
services other components or applications can make use of. To facilitate the use of
these services components have to adhere to a given specification. As Robert Englander
outlines in his book Developing JavaBeans (1997) [2], software components must
behave in ways that are expected. Its like a society of software citizens. The citizens
(components) bring functionality, while the society (environment) brings structure and
order. JavaBeans is one of Suns component models. The first specification appeared on
December 1996. As Java runs on various platforms the provision of a platform neutral
component model was one of Suns main concerns. JavaBeans offer their services by
exposing properties, events and methods. The features a component exposes can be
manipulated visually in a builder tool. This leads us directly to the next definition.
Namely the one of what a builder tool is.

1.2. Definition of a builder tool


Builder tools allow a developer to work with JavaBeans in a convenient way. By examining a JavaBean by a process known as Introspection, a builder tool exposes the
discovered features of the JavaBean for visual manipulation. A builder tool maintains
a list of all JavaBeans available. It allows you to compose the Bean into applets, application, servlets and composite components (e.g. a JFrame), customize its behavior and
appearance by modifying its properties and connect other components to the event of
the Bean or vice versa. Although the previous sentence might imply that a JavaBean
is a visual component, it has not necessarily to be one, as you will see in the following
section. There are different builder tools available, varying in functionality. The plugin
Visual Editor for Eclipse has a moderate support of JavaBeans compared to NetBeans

Sandro Antoniol

Page 4/24

Seminar Report

Figure 2: NetBeans provided property sheet to customize the FontSelector

which even allows you to develop an application consisting of JavaBeans without writing a single line of code (in best case). Figure 2 depicts the property sheet provided by
NetBeans when the FontSelector JavaBean is selected.

1.3. JavaBeans at a glance


JavaBeans can appear in two forms: visual and non visual. The former is more common,
as the majority of JavaBeans are extensions of AWT or Swing components. Some Beans
may be simple GUI elements such as a specialized button or slider. Others may be sophisticated visual software components such as a diagram component offering different
ways to present the bounded data. They all have in common that they can be customized
at design time in a builder tool. However, as already mentioned, JavaBeans can also be
non visual yet still be customizable using a builder-tool. They do not have to be derived
from a specific class or interface, albeit it is recommended that they implement the Serializable interface. In respect of the source code there is no real difference noticeable
between a JavaBean and a normal Java class. Basically what differs the source code
of a normal class from a JavaBean is that the latter adheres to the JavaBeans API
specification in terms of how it is developed. Only the strict adherence to this specifi-

Sandro Antoniol

Page 5/24

Seminar Report

cation ensures that builder tools can assist a developer to work with JavaBeans. Thus
for many solutions you can either develop a conventional Java class where you have to
write your own code for setting its properties or you can build a JavaBean which allows
you to set the properties through the builder tool. Eventually both methods result in
code just that in the latter case the builder tool creates the code automatically in the
background according to your selection(s). And as already mentioned in the best case
you do not even have to write a single line of code.

1.4. JavaBeans basic rules


A JavaBean should:
be public
implement the Serializable interface
have a no-arg constructor
be derived from javax.swing.JComponent or java.awt.Component if it is visual

2. Beans Architecture
2.1. Properties
Properties are named public attributes which determine the internal state of a JavaBean
and thus its behavior and appearance. For example, a GUI textfield might have a
property named maxlength which restricts the number of characters one can insert
into the texfield. There exist four different kinds of properties a JavaBean can expose:
Simple
Indexed
Bound
Constrained
All types of property have in common that they are characterized by a pair of set/get
methods. A getter method is used to read the value of a readable property. Its name
has to start with get, as you will see later on. To update the propertys value a setter
method has to be called. Analog to the getter-method its name has to start with set. If
a property should be read-only the latter method has to be left out. On the other side,
if the property should be write-only no getter-method has to be written. The propertys
name is determined by the name used in the pair of methods. Typically the value of a

Sandro Antoniol

Page 6/24

Seminar Report

property is stored in a private instance variable whose name matches the name of the
property. But this is not a requirement. How you name the instance variable used in
conjunction with the property is up to you.
The data type of the property can be a built-in type as well as a custom class or
interface. The following code snippet shows the naming pattern for the discussed set/get
methods:
public void set < Propertyname >( < Datatype > param ){?}
public < Datatype > get < Propertyname >(){?}

Changing a property may also lead to other actions. For instance, updating the background color property of a JavaBean might cause a repainting of the bean with its new
color.

2.2. Simple Properties


As the name suggests, simple properties are the simplest of the four. For our FontSelector
we would like to have a default font size, which will be used as initial font size at runtime.
The following code sample shows how this property is defined:
private String name = FontSelector ;
public void setName ( String name ){
this . name = name ;
}
public String getName (){
return name ;
}

If the propertys data-type is boolean the get methods can also be named is<Propertyname>.
We use a boolean variable to define whether the user can make a selection or not.
private boolean enabled ;
public void setEnabled ( boolean enabled ){
this . enabled = enabled ;
}
public boolean isEnabled (){
return enabled ;
}

2.3. Indexed Properties


If a simple property can hold an array of value they are no longer called simple but
instead indexed properties. The methods signature has to be adapted accordingly. An
indexed property may expose set/get methods to read/write one element in the array
(so-called index getter/setter) and/or so-called array getter/setter which read/write
the entire array.

Sandro Antoniol

Page 7/24

Seminar Report

public PropertyType g e t P r op e r t y N a me ( int position ) // indexed getter


public void s e t Pr o p e r t y Na m e ( PropertyType element , int position ) // indexed setter
public PropertyType [] g e t P r op e r t y N a me () // array getter
public void s e t Pr o p e r t y Na m e ( PropertyType [] list ) // array setter

The indexed methods may throw a java.lang.ArrayIndexOutOfBoundsException runtime exception in case the requested index is outside the current array bounds.
Our FontSelector bean has a string array of font names a user can choose from. The
code for that looks as following:
private String [] fonts ;
public void setFonts ( String [] fonts ) {
this . fonts = fonts ;
}
public String [] getFonts () {
return fonts ;
}
public String getFonts ( int pos ){ return fonts [ pos ]; }

2.4. Bound Properties


Bound properties notify other components of their changed value. JavaBeans follow
the Observer pattern to do this notification. Properties notifying observers about their
changes are referred to as bound properties, as most observers bind a special behaviour
to property changes.
In order to provide this notification service a JavaBean needs to have the following
two methods:
public void a d d P r o p e r t y C h a n g e L i s t e n e r ( P r o p e r t y C h a n g e L i s t e n e r p ) {
changes . a d d P r o p e r t y C h a n g e L i s t e n e r ( p );
}
public void r e m o v e P r o p e r t y C h a n g e L i s t e n e r ( P r o p e r t y C h a n g e L i s t e n e r p ) {
changes . r e m o v e P r o p e r t y C h a n g e L i s t e n e r ( p );
}

PropertyChangeListener is an interface declared in the java.beans package. Observers which want to be notified of property changes have to implement this interface,
which consists of only one method:
public interface P r o p e r t y C h a n g e L i s t e n e r extends EventListener {
public void pr op er tyC ha ng e ( P r o p e r t y C h a n g e E v e n t e );
}

Even though we could organize the list of observers by ourselves the beans package
offers a class named PropertyChangeSupport which takes over this job for us. Apart

Sandro Antoniol

Page 8/24

Seminar Report

from having methods to add/remove listeners it possesses various methods to notify the
registered observers about a changed property. In the code shown above the variable
referring an instance of this support class is named changes. The declaration code for
it looks like this:
private P r o p e r t y C h a n g e S u p p o r t changes = new P r o p e r t y C h a n g e S u p p o r t ( this );

Our FontSelector informs about changes of the currently selected font. Of course it
would be wise to make any property a bound property. However in our case we limit
it to one property in order to keep it simple. As you will see in the code below, firing
a notification requires the information which property has changed, what its old value
was and what its new value is.
private boolean bold ;
public void setBold ( boolean bold ){
if ( this . bold != bold ){
boolean wasBold = this . bold ;
this . bold = bold ;
boldBtn . setSelected ( bold );
// Notify P r o p e r t y C h a n g e L i s t e n e r s :
f i r e P r o p e r t y C h a n g e ( " bold " , wasBold , bold );
}
}
public boolean isBold (){
return bold ;
}

At this stage it is important to note that in this example there is only one instance
for all bound properties. Thus an observer can not enroll just for the notification of a
particular property. All enrolled observers are notified of any changed bound properties.
As a result, every observer needs to check on notification whether the property that
changed was the one the observer was expecting or something else. This can be easily
done by using the getPropertyName() method of the PropertyChangeEvent object
which is passed to the observer.

2.5. Constrained Properties


Constrained properties are similar to bound properties. But in addition to the latter,
constrained properties inform observers also about an imminent property change. This
allows an observer to inhibit the change of the property by throwing a
PropertyVetoException, in case the observer does not agree to this change. As the
observers which are able to put a veto on a property change do not necessarily have to
be the same which are notified after the change, a JavaBean which is constrained as well
as bound has to maintain two lists of listeners: a list of PropertyChangeListener and
a list of VetoableChangeListener.

Sandro Antoniol

Page 9/24

Seminar Report

private V e t o a b l e C h a n g e S u p p o r t vetoes = new V e t o a b l e C h a n g e S u p p o r t ( this );


public void a d d V e t o a b l e C h a n g e L i s t e n e r ( V e t o a b l e C h a n g e L i s t e n e r v ) {
vetoes . a d d V e t o a b l e C h a n g e L i s t e n e r ( v );
}
public void r e m o v e V e t o a b l e C h a n g e L i s t e n e r ( V e t o a b l e C h a n g e L i s t e n e r v ) {
vetoes . r e m o v e V e t o a b l e C h a n g e L i s t e n e r ( v );
}

By convention the set method must not handle the exception a vetoed observer threw,
rather it has to be forwarded. Hence the set method has to be declared to throw the
PropertyVetoException exception. private int currentFontSize;
private int fontSize = 11;
public void setFontSize ( int newFontSize ) throws P r o p e r t y V e t o E x c e p t i o n {
if ( fontSize != newFontSize ){
// Notify V e t o a b l e C h a n g e L i s t e n e r :
f i r e V e t o a b l e C h a n g e ( " fontSize " , fontSize , newFontSize );
int oldFontSize = fontSize ;
fontSize = newFontSize ;
// Raise event : ( see chapter Events & Methods )
n o t i f y F o n t S i z e C h a n g e d L i s t e n e r s ( newFontSize );
// It s good practise to be a bound property as well :
f i r e P r o p e r t y C h a n g e ( " fontSize " , oldFontSize , newFontSize );
}
}
public int getFontSize () {
return fontSize ;
}

As shown in the code above the property does not only notify the VetoableChangeListeners
but also the PropertyChangeListeners after the change has been performed. Even
though not beeing required it is recommend by the specification that if a property is
constrained it is also bound.

Sandro Antoniol

Page 10/24

Seminar Report

3. Events and Methods


JavaBeans can use events to communicate when something interesting happens. The
event model applied for Beans bases on the delegation-event model of AWT, introduced
in Java 1.1. There are three parts involved in this communication:
EventObject (containing information about the event)
EventListener - (the sink)
An Event Source (the Bean)
The java.util.EventObject class is the basis of all Beans events. Even though a Bean
can use EventObject instances for its events, the design pattern guidelines require that
you create your own event type by subclassing the EventObject class. The introduction
of an event requires the declaration of a new listener interface and a new event object.
Additionally the JavaBean has to supply a series of methods for the registration process.
The new interface, class and the methods have to follow a specific naming pattern, as
listed bellow:
Event object:
< EventName > Event

Event listeners interface:


< EventName > Listener

Registration process methods:


public synchronized void add < EventName > Listener ( < EventName > Listener l );
public synchronized void remove < EventName > Listener ( < EventName > Listener l );

In the following we create an event FontChanged which will be fired when a user changes
the font size.
import java . util . EventObject ;
public class F o n t S i z e C h a n g e d E v e n t extends EventObject {
private int newFontSize ;
public F o n t S i z e C h a n g e d E v e n t ( Object source , int newFontSize ) {
super ( source );
this . newFontSize = newFontSize ;
}
// Note : how you call the methods is up to you .
public int ge tN ew Fon tS iz e () {
return newFontSize ;
}
}
public interface F o n t S i z e C h a n g e d L i s t e n e r extends java . util . EventListener {

Sandro Antoniol

Page 11/24

Seminar Report

public void f o n tS i z e C h a ng e d ( F o n t S i z e C h a n g e d E v e n t e );
}

// Code FontSelector JavaBean :


// Note , that the code for the property has already been shown in the property chapter
// and is just repeated at this point for completion .
private LinkedList < FontSizeChangedListener > f o n t S i z e C h g L i s t e n e r s = new
LinkedList < FontSizeChangedListener >();
private int fontSize = 11;
public synchronized void a d d F o n t S i z e C h a n g e d L i s t e n e r ( F o n t S i z e C h a n g e d L i s t e n e r l ){
f o n t S i z e C h g L i s t e n e r s . add ( l );
}
public synchronized void r e m o v e F o n t S i z e C h a n g e d L i s t e n e r ( F o n t S i z e C h a n g e d L i s t e n e r l ){
f o n t S i z e C h g L i s t e n e r s . remove ( l );
}
protected void n o t i f y F o n t S i z e C h a n g e d L i s t e n e r s ( int newFontSize ){
LinkedList < FontSizeChangedListener > listeners =
( LinkedList < FontSizeChangedListener >) f o n t S i z e C h g L i s t e n e r s . clone ();
for ( F o n t S i z e C h a n g e d L i s t e n e r l : listeners )
l . fo n t S i z e Ch a n g e d ( new F o n t S i z e C h a n g e d E v e n t ( this , newFontSize ));
}
// Constrained Property
public void setFontSize ( int newFontSize ) throws P r o p e r t y V e t o E x c e p t i o n {
if ( fontSize != newFontSize ){
// Notify V e t o a b l e C h a n g e L i s t e n e r :
f i r e V e t o a b l e C h a n g e ( " fontSize " , fontSize , newFontSize );
int oldFontSize = fontSize ;
fontSize = newFontSize ;
fo nt Si zeS li de r . setValue ( newFontSize );
// Raise event :
n o t i f y F o n t S i z e C h a n g e d L i s t e n e r s ( newFontSize );
// It s good practise to be a bound property as well :
f i r e P r o p e r t y C h a n g e ( " fontSize " , oldFontSize , newFontSize );
}
}

3.1. Methods
Regarding methods there are no special rules for JavaBeans. If a method is public it can
be called from other components and it even allows a JavaBean to become a listener of
other Beans event(s) provided it implements the appropriate interface.

Sandro Antoniol

Page 12/24

Seminar Report

4. Instrospection
As described in the introduction, builder tools typically provide a property sheet where
one can conveniently set the properties of a JavaBean component or connect event listeners to an exposed event. In order to provide this service a builder tool needs to examine
the component for its features (=properties, events and methods). This process is referred to as introspection. To obtain information about a specific JavaBean one can
use the static getBeanInfo() method of the Introspector class. This method returns
an instance of the BeanInfo class, which describes all features a JavaBean exposes. The
use of this method is shown in the following code fragment:
FontSelector fs = new FontSelector ();
BeanInfo bi = Introspector . getBeanInfo ( fs . getClass ());

The most important methods of the BeanInfo object will now be described in the following sections.

4.1. Methods of the BeanInfo class


4.1.1. Events
To determine what events a JavaBean can fire, the BeanInfo object provides the method
getEventSetDescriptors which returns an array of EventSetDescriptors. As the
name suggests an EventSetDescriptor is a class describing an event. In our example
we use the getName() method to display the name of the events.
E v e n t S e t D e s c r i p t o r [] esd = bi . g e t E v e n t S e t D e s c r i p t o r s ();
for ( int i =0; i < esd . length ; i ++){
System . out . print ( esd [ i ]. getName () + " " );
}

4.1.2. Properties
The determination of properties works similar to the event determination. The method
getPropertyDescriptors() returns an array of PropertyDescriptors reporting all
properties of a Bean.
P r o p e r t y D e s c r i p t o r pd [] = bi . g e t P r o p e r t y D e s c r i p t o r s ();
for ( int i =0; i < pd . length ; i ++)
System . out . print ( pd [ i ]. getName () + " " );

4.1.3. Method
Its no surprise that the methods determination works the same way just with different
names. Note, that only public methods of the Bean will be reported. For each method

Sandro Antoniol

Page 13/24

Seminar Report

descriptor, the parameters types for the described methods can be discovered through
the getParameterDescriptors() method.
M e t h o d D e s c r i p t o r md [] = bi . g e t M e t h o d D e s c r i p t o r s ();
for ( int i =0; i < md . length ; i ++)
System . out . print ( md [ i ]. getName () + " " );

4.2. Personalized Bean information with BeanInfo


By default an Introspector uses the Reflection API to determine the features of a
JavaBean. However, a JavaBean can provide its own BeanInfo which will be used
instead by the Introspector to determine the discussed information. This allows a
developer hiding specific properties, events and methods from a builder tool or from
any other tool which uses the Introspector class. Moreover it allows supplying further
details about events/properties/methods as you are in charge of creating the descriptor
objects. Hence you can, for example, call the setShortDescription() method to set a
descriptive description. A BeanInfo class has to be derived from the SimpleBeanInfo
class and its name has to start with the name of the associated JavaBean. At this
point it has to be underlined that the name of the BeanInfo class is the only relation
between a JavaBean and its BeanInfo class. If in the example below the class was named
FontSelector_BeanInfo (note the underline) the Introspector would not recognize
the class as BeanInfo class of the FontSelector JavaBean.
import java . beans .*;
public class F o n t S e l e c t o r B e a n I n f o extends Si mp le Bea nI nf o {
private final static Class beanClass = FontSelector . class ;
public P r o p e r t y D e s c r i p t o r [] g e t P r o p e r t y D e s c r i p t o r s () {
P r o p e r t y D e s c r i p t o r [] properties = new P r o p e r t y D e s c r i p t o r [3];
try {
properties [0] = new P r o p e r t y D e s c r i p t o r ( " fontSize " , FontSelector . class );
properties [0]. se tC ons tr ai ned ( Boolean . TRUE );
properties [0]. se tD isp la yN ame ( " Fontsize " );
properties [1] = new P r o p e r t y D e s c r i p t o r ( " bold " , FontSelector . class );
properties [1]. setBound ( Boolean . TRUE );
properties [1]. se tD isp la yN ame ( " Bold " );
properties [2] = new P r o p e r t y D e s c r i p t o r ( " fonts " , FontSelector . class );
properties [2]. se tD isp la yN ame ( " Fonts " );
properties [2]. s e t S h o r t D e s c r i p t i o n ( " List of fonts one can choose from " );
}
catch ( I n t r o s p e c t i o n E x c e p t i o n e ) {
e . pr i n t S t a ck T r a c e ();
}
return properties ;
}
}

Sandro Antoniol

Page 14/24

Seminar Report

5. Persistence
Persistence is the ability of an object to store its state. [5] JavaBeans use the Java
Serialization API to gain this ability. The simplest way to enable serialization of a Bean
is by implementing the Serializable interface. The points you have to consider when
declaring a Bean to be serializable are the same as for any other serializable object (e.g.
how to deal with transient and static variables, whether a validation is required upon
deserialization etc.). The greatest strength of persistence regarding JavaBeans lies in
the ability to create prototypes a new JavaBean can be instantiated from. For example,
a Java application using our FontSelector Bean can serialize the Bean on a Microsoft
Windows machine, the serialized file can be sent to a Linux machine, where another Java
application can instantiate a new Bean with the exact state (same fonts, fontsize etc.)
its counterpart had on the Windows machine. Although serialization is a convenient way
to persist a JavaBean this method has a downside. Serialization is intended to persist an
object for a short time, for example to transfer the object to a remote machine through
Java RMI (Remote Machine Invocation). But JavaBeans are typically persisted to serve
as a prototype that requires a mechanism for long-term persistence. The solution is to
represent the JavaBean in a XML structure, which is topic of the next section.

5.1. Long-term persistence


The beans package supplies the XMLEncoder class, which enables JavaBeans to be saved
in XML format. The use of the XMLEncoder is pretty straightforward. The following
code fragment illustrates how to generate a XML file representing a FontSelector class
instance with its internal state.
FontSelector fs = new FontSelector ();
fs . setFontSize (14);
fs . setFonts ( new String [] { " Arial " , " Verdana " , " Times " });
XMLEncoder encoder = new XMLEncoder (
new B u f f e r e d O u t p u t S t r e a m (
new F i l e O u t p u t S t r e a m ( " FontSelector . xml " ) ) );
encoder . writeObject ( fs );
encoder . close ();

The resulting XML file looks as follows:


<? xml version = " 1.0 " encoding = " UTF -8 " ? >
< java version = " 1.6.0 " class = " java . beans . XMLDecoder " >
< object class = " ch . fhnw . ec . fontselector . FontSelector " >
< void property = " fontSize " >
<int >14 </ int >
</ void >
< void property = " fonts " >
< array class = " java . lang . String " length = " 3 " >

Sandro Antoniol

Page 15/24

Seminar Report

< void index = " 0 " >


< string > Arial </ string >
</ void >
< void index = " 1 " >
< string > Verdana </ string >
</ void >
< void index = " 2 " >
< string > Times </ string >
</ void >
</ array >
</ void >
</ object >
</ java >

5.2. Bean Reconstitution


A JavaBean is reconstituted from its serialized state by deserialization. This can be
either done in conventional fashion by using a ObjectInputStream object or by using
the static java.beans.Beans.instantiate() method, which most builder tools make
use of. This method looks for a file named Classname.ser. If such a file exists the class
is deserialized and returned. Otherwise, the Bean will be created by using the default
no-arg constructor of the class.
FontSelector fs = ( FontSelector ) Beans . instantiate ( null , " FontSelector " );

However, this method can not be used if a bean has been stored in XML format. In this
case the XMLDecoder class has to be used for reading the XML file and returning the
reconstituted object.
XMLDecoder decoder = new XMLDecoder (
new B u f f e r e d I n p u t S t r e a m (
new F i l eI n p u t S t re a m ( " FontSelector . xml " ) ) );
FontSelector fs = ( FontSelector ) decoder . readObject ();
decoder . close ();

6. BeanContext
A set of related JavaBeans can be logically grouped into a context. This context can
be thought of as a containing environment and is known as BeanContext. As stated in
Suns tutorial about using the BeanContext API, there are two distinct types of BeanContexts: one which supports membership only (interface
java.beans.beancontext.BeanContext) and one which supports membership and offers services (interface java.beans.beancontext.BeanContextServices) to its JavaBeans nested within. BeanContexts follow the Composite Pattern, where BeanContext
classes are the composite. Thus a BeanContext can not only host JavaBeans but also
BeanContext objects.

Sandro Antoniol

Page 16/24

Seminar Report

For each interface the BeanContext API offers a helper class with the basic BeanContext
and the BeanContextServices functionality respectively. For the BeanContext interface the helper class is called BeanContextSupport and for the BeanContextServices
interface BeanContextServicesSupport.
As both classes implement the Collection interface, they can be handled like a collection in terms of adding, removing and retrieving JavaBeans. In case a JavaBean
wishes to obtain a reference to its context when being added to the context it shall
implement the BeanContextChild interface.
In the following we focus on the BeanContextServicesSupport class. As already mentioned this class offers services to its hosted beans. The services are supplied by so called
service providers, which can be registered with the context via the contexts addService()
method. JavaBeans that implement the
java.beans.beancontext.BeanContextServicesListener interface and have been registered as a BeanContextServicesListener will be notified of new added services.
JavaBeans can query the context they are residing in for a list of available services
(getCurrentServiceClasses() ), or ask for a specific service by name using the
getService() method. In a hierarchy of contexts a service request will be forwarded
to the parent context if the request can not be fulfilled. A registered service can also be
removed from a context via the contexts removeService() method.
In Appendix A an example application illustrates the use of the BeanContext functionality. The example has been taken from Suns JavaBean Tutorial and has no relation to
the FontSelector JavaBean which has been referred to in other code fragments shown in
this report.

7. The Beans class


The Beans class found in java.beans is not meant to be instantiated. It consists of a few
static methods, the most interesting of them (from my point of view) will be outlined in
the following. The instantiate() method has already been mentioned in chapter 5.2.
As its name suggests, the method isDesignTime() informs about whether a JavaBean
is running at design-time, viz, running inside an application builder environment. Using
this method allows a JavaBean, for example, having different appearances at design- and
run-time. The setDesignTime() method is used to set the environment a JavaBean is
running in. Similarly, setGuiAvailable() and isGuiAvailable() sets and informs
whether a GUI is available (depends on the Java Virtual Machine).

Sandro Antoniol

Page 17/24

Seminar Report

8. Conclusion
This report addressed various aspects of the development of JavaBeans. We introduced
the term of software components and got to know what JavaBeans are and what their aim
is. We got acquainted with the JavaBean specification API and learned how to obtain
information about a JavaBean and how we can influence this information. Moreover
we examined the methods to persist a JavaBean, described the BeanContexts and some
methods of the Beans class. However, as already announced in the abstract, not all
aspects could be covered in this report. The interested reader is kindly referred to Suns
JavaBeans Tutorial for more information, for example, about how to provide a dialog
for customizing a JavaBean (referred to as Bean Customization). The tutorial can be
found at: http://java.sun.com/docs/books/tutorial/javabeans

Sandro Antoniol

Page 18/24

Seminar Report

9. References

[1] Cervantes, H. (2002). The JavaBeans Component Model


Retrieved March 30, 2007, from
http://www.humbertocervantes.net/beansdiscussion.html
[2] Englander, R. (1997). Developing Java Beans
Retrieved March 30, 2007, from
http://www.oreilly.com/catalog/javabeans/chapter/ch01.html
[3] Prof. Dr. Ostermann, K.; Dipl.-Inform. Aracic, I.; Dipl.-Inform. Kloppenburg, S.
(2006). Introduction to JavaBeans Component Model
Retrieved April 1, 2007, from
http://www.st.informatik.tu-darmstadt.de/pages/lectures/sct/ss06/lectures/V2 JavaBeans.pdf
[4] MageLang Institute. (1997). JavaBeans Short Course: Introduction to JavaBeans
Retrieved March 24, 2007, from
http://java.sun.com/developer/onlineTraining/Beans/JBShortCourse/beans.html
[5] Sun. (2006). JavaBeans(TM) (The JavaT M Tutorials)
Retrieved March 24, 2007, from
http://java.sun.com/docs/books/tutorial/javabeans

Sandro Antoniol

Page 19/24

Seminar Report

A. Sample BeanContext applicaton


On the next page an example application illustrates the use of the BeanContext environment. The example has been taken from Suns JavaBean Tutorial and has no relation
to the FontSelector JavaBean which has been referred to in other code fragments shown
in this report. The application uses a word counting service to count the number of
words in a given text file. [5]

Sandro Antoniol

Page 20/24

Seminar Report

A Word Counting Service Example


The classes defined in this sample application are:

DocumentBean.java: A JavaBean that encapsulates a File object. Create an instance of


this bean by passing it a String indicating the name of the text file to represent. This bean
extends BeanContextChildSupport, which allows it to listen for addition/revocation of
services in its context. When the bean detects that a WordCount service has been added to the
context, it requests the service to count the number of words it contains.
WordCountServiceProvider.java: A class that acts as the factory for delivering the
WordCount service. This class implements the BeanContextServiceProvider
interface.
WordCount.java: This interface defines the service itself.
DocumentTester.java: The main test program.

File: DocumentBean.java
import java.beans.beancontext.*;
import java.io.*;
import java.util.*;
/**
* A JavaBean that encapsulates a text file. When added to a bean context,
* this bean listens for a WordCount service to become available. When
* the service does become available, the DocumentBean requests an
* instance of the service. The service then counts the number of words in the
file,
* and prints a report to standard output.
*/
public final class DocumentBean extends BeanContextChildSupport {
private File document;
private BeanContextServices context;
/**
* Creates a new DocumentBean given the name of the file to read from.
* @param fileName the name of the file to read from
*/
public DocumentBean(String fileName) {
document = new File(fileName);
}
/**
* Called when this bean detects that a new service
* has been registered with its context.
*
* @param bcsae the BeanContextServiceAvailableEvent
*/
public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) {
System.out.println("[Detected a service being added to the context]");
// Get a reference to the context
BeanContextServices context = bcsae.getSourceAsBeanContextServices();
System.out.println("Is the context offering a WordCount service? "
+ context.hasService(WordCount.class));
// Use the service, if it's available
if (context.hasService(WordCount.class)) {
System.out.println("Attempting to use the service...");
try {
WordCount service = (WordCount)context.getService(this, this,
WordCount.class,
document, this);
System.out.println("Got the service!");
service.countWords();
} catch(Exception e) { }

Sandro Antoniol

Page 21/24

Seminar Report

}
}
/**
* Called when this bean detects that a service
* has been revoked from the context.
*
* @param bcsre the BeanContextServiceRevokedEvent
*/
public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
System.out.println("[Detected a service being revoked from the
context]");
}
}

File: WordCountServiceProvider.java
import java.beans.beancontext.*;
import java.util.*;
import java.io.*;
/**
* This class is the factory that delivers a word counting service.
* The 3 methods defined in this class are the concrete implementations
* of the BeanContextServiceProvider interface. For this demonstration, the
primary
* method of interest is getService(). The getService() methods returns a new
* WordCount instance. It is called by the bean context when a nested
* JavaBean requests the service.
*/
public final class WordCountServiceProvider implements BeanContextServiceProvider
{
public Object getService(BeanContextServices bcs,
Object requestor,
Class serviceClass,
Object serviceSelector) {
// For this demo, we know that the cast from serviceSelector
// to File will always work.
final File document = (File)serviceSelector;
/* Return an instance of the service. The service itself is
* the WordCount interface, which is implemented here using
* an anonymous inner class.
*/
return new WordCount() {
public void countWords() {
try {
// Create a Reader to the DocumentBean's File
BufferedReader br = new BufferedReader(new
FileReader(document));
String line = null;
int wordCount = 0;
while ((line = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line);
while (st.hasMoreTokens()) {
System.out.println("Word " + (++wordCount)
+ " is: " + st.nextToken());
}
}
System.out.println("Total number of words in the document: "
+ wordCount);
System.out.println("[WordCount service brought to you by
WordCountServiceProvider]");
br.close();
} catch(Exception e) { }
}
};
}

Sandro Antoniol

Page 22/24

Seminar Report

public void releaseService(BeanContextServices bcs,


Object requestor,
Object service) {
// do nothing
}
public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class
serviceClass) {
return null; // do nothing
}
}

File: WordCount.java
/**
* The WordCount service. Implementations of the
* countWords() method are provided by the
* WordCountServiceProvider class.
*/
public interface WordCount {
/**
* Counts the number of words in the file.
*/
public abstract void countWords();
}

File: DocumentTester.java
import java.beans.beancontext.*;
import java.util.*;
/**
* A test program that creates all of the objects,
* a tests the service capabilities. Run this program
* from the command line using java DocumentTester
*/
public class DocumentTester {
public static void main(String[] args) {
BeanContextServicesSupport context = new BeanContextServicesSupport();
// a bean context
DocumentBean doc1 = new DocumentBean("Test.txt");
context.add(doc1);
context.addBeanContextServicesListener(doc1); // listen for new
services
WordCountServiceProvider provider = new WordCountServiceProvider();
context.addService(WordCount.class, provider); // add the service to
the context
}
}

File: Test.txt
This

text will

be analyzed

by the WordCount
service.

Output:
[Detected a service being added to the context]
Is the context offering a WordCount service? true
Attempting to use the service...
Got the service!
Word 1 is: This
Word 2 is: text
Word 3 is: will

Sandro Antoniol

Page 23/24

Seminar Report

Word 4 is: be
Word 5 is: analyzed
Word 6 is: by
Word 7 is: the
Word 8 is: WordCount
Word 9 is: service.
Total number of words in the document: 9
[WordCount service brought to you by WordCountServiceProvider]

Sandro Antoniol

Page 24/24

Potrebbero piacerti anche