Java Beans
Java Beans
Seminar Report
Antoniol, Sandro, TIE04
FHNW
Hochschule f
ur Technik
Studiengang I
Supervisor:
Prof. Dr. Dominik Gruntz
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.
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
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
13
13
13
13
13
14
5. Persistence
15
5.1. Long-term persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2. Bean Reconstitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
6. BeanContext
16
17
8. Conclusion
18
9. References
19
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.
Sandro Antoniol
Page 4/24
Seminar Report
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.
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.
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.
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 ;
}
Sandro Antoniol
Page 7/24
Seminar Report
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 ]; }
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.
Sandro Antoniol
Page 9/24
Seminar Report
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
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 );
}
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.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 () + " " );
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.
Sandro Antoniol
Page 15/24
Seminar Report
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.
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
Sandro Antoniol
Page 19/24
Seminar Report
Sandro Antoniol
Page 20/24
Seminar Report
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
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