Anda di halaman 1dari 21

1

What are JavaBeans ?


• A Bean is a reusable software component.

• JavaBeans is a set of reusable software components written in java

• JavaBeans is a new technology that is used to construct applications


by configuring and connecting components called Beans
Why JavaBeans

• Beans can be created or can be got in binary format from vendors



• These building blocks need to be designed, coded and tested only once
and can be reused in multiple applications.

• Creating a Bean is just like creating any other java program

• JavaBeans led to a new type of programmer called the component
assembler who uses well defined components to create more functionality

JavaBeans the Self-Contained Component


• JavaBeans adds to the Java platform the capability to create a complete
application by simply linking together a set of self-contained components

• There is no restriction on the size or complexity of a JavaBeans component

• The philosophy behind JavaBeans is to provide easy to implement
functionality for the component
• JavaBeans is based on the reuse and interoperability of Bean components
JavaBeans and Containers

Container Container

JavaBean1
JavaBean

JavaBean2
2
Concepts in Component Model
JavaBeans provides a platform neutral component architecture
The features of JavaBeans are
• Component fields or properties
• Component methods or functions
• Events and intercommunication
• State persistence and storage

Component fields or properties


• A Component will have a set of properties that define its state
eg. A component to display text
Foreground color
Type of font
Size of font

If the properties of one component match that of another then they are
in the same state

Properties not only define the appearance but also the behavior of
components

A component may not have any appearance at all but can have behavior
eg. A component in a spreadsheet that calculates the interest earned on
some earning column but not capable of displaying the data

• Properties can range from boolean values, strings, arrays to other


components

• Components can also be independent

Component methods or functions


• API of a component is the collection of methods or functions that it
contains so that other components and containers can call

• A container can modify a component’s properties and notify it as an event

• Different component models differ in how they make properties and
methods of their components available to other components

Events and Intercommunication


• A component by itself is a lonely component
• A component becomes useful when it is used in conjunction with other
components
• The method by which one component communicate with another
component is event transmission
• A component undergoes some action causing it to generate an event
• An event can also be generated when a button is clicked
• When an event happens the component will notify other interested
components depending on the model
3
State Persistence and Storage
• The components should remember their state and is very important
• If an application remembers the size and position of its window when it
was last closed it is maintaining a persistent state
• The capability to store and retrieve components is called packing
• In a distributed environment where the components are served up over
a network it is important to store and retrieve components

The Basics of Designing a JavaBean


• Designing a Bean directly affects the way it behaves in a container
• The names chosen for the methods should follow specific design
specifications
• If the Bean is designed with proper rules then when the Bean participate
in Introspection there will be no need for additional programming
Designing a Bean consists of the following steps
• Specifying the Bean’s properties
• Specifying the events the Bean generates or responds to
• Defining which properties, methods, and events the Bean exposes to
other Beans or to its container
• Deciding miscellaneous issues, such as whether the Bean has its own
Customization dialog box or whether it requires some prototypical
state information
• Designing a Bean can be more explained with the help of an example
• There are two Beans a Bean to enter text and another Bean to display
the text
• The two Beans are placed in a container so that one Bean can be used to
enter text and the other Bean to display it.
• There can be a number of questions about the properties of the Beans
• The first thing a Bean needs is a name and they are TextDisplayer and
TextReader

Specifying the Bean’s Properties

The TextDisplayer and TextReader Beans should have property defining


the text they hold

Property Name Java Type

OutputText java.lang.String
Property Name Java Type
BGColor java.awt.Color
InputText java.lang.String
TextFont java.awt.Font
FontColor java.awt.Color Width int
TextDisplayer Bean Properties TextReader Bean Properties
4
Specifying the Events the Bean Generates or Responds To
• The TextDisplayer Bean must respond to an event specifying that its
text should change
• The TextDisplayer must update its OutputText property and redraw itself
• The TextReader Bean doesn’t need to respond to any event but should
generate an event when the user changes its InputText property
• This type of event is called a PropertyChangeEvent

Properties, Methods and Event Exposure


• These Beans are simple so there is no need to hide anything from the
Bean’s container or other Beans interested in them
• Java Beans provides a mechanism that will use methods to extract
the names and types of the properties and events

Initial Property Values and Bean Customizers

The Beans TextDisplayer and TextReader have a predefined state when

they are instantiated and they use standard PropertyEditors for their

properties

Property Name Default Value

TextOutput “TextDisplayer”

BGColor java.awt.Color.white
TextFont Courier, normal, 12
FontColor java.awt.Color.black
Default Property Values for the TextDisplayer Bean

Initial Property Values and Bean Customizers (contd.)

Property Name Default Value

InputText “ “ (an empty string)

Width 40
Default Property Values for the TextReader Bean

public class TextDisplayer extends Canvas implements


PropertyChangeListener {

// default constructor for this Bean. This is the constructor that an application
// builder would use.

public TextDisplayer() {

this( "TextDisplayer", Color.white, new Font( "Courier", Font.PLAIN, 12 ),


5
Color.black ); }
// custom constructor for this Bean.
public TextDisplayer( String OutputText, Color BGColor,
Font TextFont, Color FontColor ) {
super(); // call the Canvas's constructor.
this.OutputText = OutputText;
this.BGColor = BGColor;
this.TextFont = TextFont;
this.FontColor = FontColor;
setFont( TextFont ); // set the Canvas's font.

setBackground( BGColor ); // set the Canvas's background color.

setForeground( FontColor ); // set the Canvas's foreground color.


}

// this Bean's properties.

protected String OutputText;

protected Color BGColor, FontColor;

protected Font TextFont; }


The Bean implement an interface called PropertyChangeListener and is used
so that the TextDisplayer Bean can update its OutputText property by
receiving an event

public class TextReader extends TextField {

// default constructor for this Bean. This is the constructor that an

application builder
// would use.

public TextReader() {

this( "", 40 ); }

// custom constructor for this Bean.

public TextReader( String InputText, int Width ) {

super( InputText, Width );

this.InputText = InputText;
this.Width = Width;

setEditable( true );

}
6

// this Bean's properties.

protected String InputText;

protected int Width;

}
Creating and Using Properties

• The TextDisplayer Bean display in black fonts in white background as the
property is set like that and the FontColor property can be changed
according to the users wish.
• If the property of a component cannot be changed by other Beans the
usefulness and reusability of the Bean is reduced.
eg. Bean’s FontColor property to red to indicate a negative value
• Four types of properties are associated with a JavaBean
• Single value property – is a property for which there is only one value
• Indexed property – an indexed property has several values each of which
has a unique index
• Bound property – a property is bound means that some other Bean is
dependent on that property. eg. TextDisplayer and TextReader
• Constrained property – a property is constrained if it must check with
other components before it can change and constrained properties
cannot change arbitrarily

Single Value Properties

• There are two types of properties Readable properties and Writable


properties
• Readable properties have a getter method used to read the value of the
property
• Writable properties have a setter method used to change the value of the
property
• These methods not only return the value of a property but also can
perform calculations and return some other value.

• The method by which other components and methods learn about a


Bean’s properties is called Introspection

• The class java.beans.Introspector provides introspection information to
other components
• The Introspector class traverses the class hierarchy of a particular Bean
and finds explicit information provided by the Bean and uses it.

• Introspector uses design patterns to extract implicit information from
those Beans that do not provide explicit information

• Specific design rules should be applied when defining accessor methods
so that the Introspector class can get the Bean properties easily
7
• A BeanInfo class can be supplied to expose a Bean’s properties
• The design patterns that should be used when defining accessor
methods are of the following format

Public void set<PropertyName> (<PropertyType> value );


Public <PropertyType> get<PropertyName>();
Public boolean is<PropertyName>();
• The last pattern is an alternative getter method for Boolean properties
Only
• Setter methods can allowed to throw exceptions if they need

• The accessor methods for the TextDisplayer Bean is as follows

public synchronized String getOutputText() {

return( OutputText ); }

public synchronized void setOutputText( String text ) {

OutputText = text;

resizeCanvas(); }
public synchronized Color getBGColor() {

return( BGColor ); }

public synchronized void setBGColor( Color color ) {

BGColor = color;

setBackground( BGColor ); // set the Canvas's background color.

repaint(); }

public synchronized Font getTextFont() {

return( TextFont ); }

public synchronized void setTextFont( Font font ) {

TextFont = font;

setFont( TextFont ); // set the Canvas's font.

resizeCanvas(); }

public synchronized Color getFontColor() {

return( FontColor ); }
8
public synchronized void setFontColor( Color color ) {

FontColor = color;

setForeground( FontColor ); // set the Canvas's foreground color.

repaint(); }

• All the accessor methods have been declared synchronized assuming


that the Beans are running in multithreaded environments

• Using synchronized accessor methods helps prevent race conditions
from forming

• The following figure shows the property sheet of Sun’s BeanBox for the
TextDisplayer Bean

Indexed Properties

All indexed properties must be Java integers.


• Indexed properties can be read individually or as an entire array.

• The design patterns for indexed properties are as follows

public <PropertyType> get<PropertyName>( int index );


public void set<PropertyName>(int index, <PropertyType> value);
public <PropertyType>[ ] get<PropertyName>();
Public void set<PropertyName> ( <PropertyType>[ ] value );
9

Bound Properties
• The programmer can decide which all Bean properties other components
can bind to
• To provide bound properties in a Bean the following methods must be defined
public void addPropertyChangeListener( PropertyChangeListener 1 );
public void removePropertyChangeListener( PropertyChangeListener 1 );

To provide this functionality on a per-property basis the following design pattern should be used.
public void add<PropertyName>Listener( PropertyChangeListener 1 );
public void remove<PropertyName>Listener( PropertyChangeListener 1 );

• Beans which want to bind to other components properties should
implement the PropertyChangeListener interface which consists of
the following method
public void propertyChange( PropertyChangeEvent evt );

• Whenever a bound property in a Bean is updated it must call the
propertyChange() method in all the components that have registered
with it

• The class java.beans.PropertyChangeSupport helps to call all the


components that have registered with the property
• The following code shows what is required in the TextReader Bean to allow
its InputText property to be bound.

// setter method for the InputText property.

public synchronized void setInputText( String newText ) {

String oldText = InputText;

InputText = newText;

setText( InputText );

changeAgent.firePropertyChange( "inputText", new String( oldText ),

new String( newText ) ); }

// these two methods allow this Bean to have bound properties.

public void addPropertyChangeListener( PropertyChangeListener l ) {

changeAgent.addPropertyChangeListener( l ); }

public void removePropertyChangeListener( PropertyChangeListener l ) {


10
changeAgent.removePropertyChangeListener( l ); }

protected PropertyChangeSupport changeAgent = new

PropertyChangeSupport( this );

Constrained Properties

• The process for providing constrained properties is by defining the


following methods in the Bean

public void addVetoableChangeListener( VetoableChangeListener 1 );


public void removeVetoableChangeListener( PropertyChangeListener 1 );

• To provide this functionality on a per-property basis the following design
pattern should be used.

public void add<PropertyName>Listener( VetoableChangeListener 1 );


public void remove<PropertyName>Listener( VetoableChangeListener 1 );

• Beans intended to constrain other components properties should
implement the VetoableChangeListener interface which consists of
the following method

public void VetoableChange( PropertyChangeEvent evt );



• Whenever a constrained property in a Bean is updated it must call the
VetoableChange() method in all the components that have registered
with it
• The class java.beans.VetoableChangeSupport helps to call all the
components that have registered with the property
• The following code shows what is required in the TextReader Bean to allow
its Width property to be constrained

// setter method for the Columns property.

public synchronized void setWidth( int newWidth )

throws PropertyVetoException {

int oldWidth = Width;

vetoAgent.fireVetoableChange( "width", new Integer( oldWidth ),

new Integer( newWidth ) );

// no one vetoed, so change the property.


11
Width = newWidth;

setColumns( Width );

Component p = getParent();

if ( p != null ) { p.invalidate(); p.layout(); }

changeAgent.firePropertyChange( "width", new Integer( oldWidth ),

new Integer( newWidth ) ); }

// these two methods allow this Bean to have constrained properties.

public void addVetoableChangeListener( VetoableChangeListener l ) {

vetoAgent.addVetoableChangeListener( l ); }

public void removeVetoableChangeListener( VetoableChangeListener l ) {

vetoAgent.removeVetoableChangeListener( l ); }

protected VetoableChangeSupport vetoAgent = new

VetoableChangeSupport( this );

• In the program the width property is bound and constrained

• A property does not have to be bound to be constrained

• To make the Width property constrained but not bound is to remove the line

changeAgent.firePropertyChange( "width", new Integer( oldWidth ),

new Integer( newWidth ) );

Using Events to Communicate with Other Components



• The idea behind JavaBeans component model is to provide
reusable components
• The Beans must be able to communicate with other Beans and their
container and this is accomplished by means of Listener
interfaces.
• Beans use the same event handling scheme as AWT that is if a Bean
needs to hear about events coming from another Bean it must
register itself with that Bean
• A Bean can hear events coming from another Bean by implementing

the Listener interface for the event of interest.


• If a Bean is no longer interested in hearing from another Bean then
12
it must unregister itself with that Bean.
• Any event that a Bean wants to fire must inherit from the class
java.util.EventObject.
• The event handling method of a Listener interface should follow the
design pattern for Introspection as shown
Void <EventOccuranceName> (<EventObjectType> evt);

• The <EventObjectType> inherits from java.util.EventObject


• An event handler method can throw exceptions
• One Listener interface can have any number of related event handlers.
• There are two types of events that components can listen for and are
Multicast events – there can be any number of listeners
Unicast events – can have only one listener

Multicast Events

• Multicast events are the most common types of events



• The PropertyChangeEvent is a multicast event because there can be
any number of listeners

• The addPropertyChangeListener() and
removePropertyChangeListener() methods are used with
components to register with a Bean when a bound property
change the same is used with multicast events also

public synchronized void add <ListenerType>( < ListenerType> listener );


public synchronized void remove <ListenerType>( < ListenerType> listener );

Unicast Events

• Unicast events do not occur as often as multicast events



• Unicast events can have only one listener

• If more than one component attempt to listen to the unicast event a
java.util.TooManyListenersException will be thrown

• The following design pattern is used when declaring unicast events
public synchronized void add <ListenerType>( < ListenerType> listener ) throws java.util.
TooManyListenersException;
public synchronized void remove<ListenerType> (<ListenerType> listener);

Introspection : Creating and Using BeanInfo Classes

• Introspection is the most important aspect of JavaBeans because


without it a container cannot do anything with a Bean other than
display it
• The java.beans.Introspector class does all the pattern analysis to
expose the properties, methods and events that a component has
13
• The java.beans.Introspector class looks to see whether a BeanInfo
class is defined for the Bean it is inspecting

• If a BeanInfo class is found then the introspector does not do any

pattern analysis on the areas of the Bean for which the BeanInfo

class supplies information


• As an example let us design a BeanInfo class for the TextDisplayer
Bean
• The first thing is to define what information to provide and what to
leave up to the Introspector class to analyze
• We provide the properties of the Beans and let the Introspector

class use analysis to expose the events and methods

• The following table shows the names of the TextDisplayer Bean’s

properties and the user friendly names to be displayed

Property Name User-friendly Name

OutputText “Text String”

BGColor “Background Color”


TextFont “Text Font”
FontColor “Text Color”
The TextDisplayer Bean’s Properties and User-Friendly Names

• The BeanInfo class is named TextDisplayerBeanInfo.class



• The Introspector class looks for BeanInfo information by
appending BeanInfo to the class name of the Bean it is currently
analyzing
• All BeanInfo classes must implement the java.beans.BeanInfo
interface

• The Introspector class has a set procedure for the way it looks for

information and they are


1. The Introspector class looks for a BeanInfo class for the Bean it
is analyzing

2. If a BeanInfo class is present each method in the BeanInfo class is called to find out
whether it can provide any information.
The Introspector class will use implicit analysis to expose
information for which the BeanInfo class denies any knowledge
14

( returns a null value). If no BeanInfo class is found the

Introspector class will use implicit analysis for all the methods in

the java.beans.BeanInfo interface

3. The Introspector class then checks to see whether it has

obtained explicit information for each of the methods in the

BeanInfo interface. If it has not it steps into the parent class

( if one exists) and starts the process over for only those

methods that it had to use analysis on.

4.When the Introspector class has gotten information from a

BeanInfo class for all the methods in the java.beans.BeanInfo

interface or when there are no more parent classes to explore

the Introspector class returns its results

• The Sun microsystems has provided a prebuilt class called


java.beans.SimpleBeanInfo that returns a null value for all the
BeanInfo methods
• The prebuilt class helps to inherit and override only the methods that
is required
• The following is the BeanInfo class for the TextDisplayer Bean

import java.beans.*;

public class TextDisplayerBeanInfo extends SimpleBeanInfo {

// override the getPropertyDescriptors method to provide that info.

public PropertyDescriptor[] getPropertyDescriptors() {

PropertyDescriptor[] properties = new PropertyDescriptor[4];

try {

properties[0] = new PropertyDescriptor(

"Text String", BeanClass, "getOutputText", "setOutputText" );

properties[1] = new PropertyDescriptor(


15
"Text Color", BeanClass, "getFontColor", "setFontColor" );

properties[2] = new PropertyDescriptor(

"Text Font", BeanClass, "getTextFont", "setTextFont" );


properties[3] = new PropertyDescriptor(

"Background Color", BeanClass, "getBGColor", "setBGColor" );

} catch( IntrospectionException e ) {

return( null ); // exit gracefully if we get an exception.

return( properties ); }

private Class BeanClass = TextDisplayer.class;

}
• The getPropertyDescriptors() method is overriden in the program

• The parent class returns null for all the other methods in the
java.beans.BeanInfo interface.

• If a java.beans.IntrospectionException is catch then it means an

incorrect getter or setter method name was given


• If an IntrospectionException is catch a null value should be returned
so that the Introspector class can still analyze the Bean.
• The following figure shows the PropertySheet window of Sun’s
BeanBox for the TextDisplayer Bean
• The user friendly names have been used instead of the parent
classes properties
16

Customization: Providing Custom PropertyEditors and GUI Interfaces


• Properties of a Bean have a Property Editor

• In the Property window next to the Text String label there is a
TextField AWT component already filled with the value of the
OutputText property

• The value is not supplied by the user the BeanBox application asks
the java.beans.PropertyEditorManager what the default
PropertyEditor was for an object of type java.lang.String and
displays it

• It is not a must that a Bean should have a GUI Environment as the
PropertyEditor and Customizer needs
eg. a Bean designed to run on a server does not need a GUI
Environment
• The java.beans.Beans class and the java.beans.Visibility interface
allows Beans to have different behavior in GUI and non-GUI
Environments

PropertyEditors and the PropertyEditor Manager



• Java.beans.PropertyEditorManager provides default
PropertyEditors for majority of Java classes

• For a custom property type there is no default PropertyEditor so
the designer should provide his own PropertyEditor

• This can be done by providing an additional class by appending
Editor to the class name that the PropertyEditorManager can use

• The requirements of a PropertyEditor are as follows
1. Custom PropertyEditors must inherit from java.awt.Component so
that they can be displayed in a property sheet
eg. Inheriting from an AWT component like java.awt.TextField

2. Custom PropertyEditors must derive their class name by


postfixing Editor to the property class name unless they register
themselves with the PropertyEditorManager
eg.The PropertyEditor for a custom property type
CustomProperty.class must be named
CustomPropertyEditor.class

3. The custom PropertyEditors that do not follow the standard


naming convention must register itself with the containers
PropertyEditorManager by calling the registerEditor() method

4. Custom PropertyEditors must always fire a PropertyChange event


17
to update the custom property otherwise the container has no way
of knowing to update the component

Customization Editor
• All application builders have to implement some method of
customizing the Beans

. Bean developers can optionally supply customizer classes with their


Beans to be used in place of standard property sheets

• To implement a customizer class a Bean must also provide a
BeanInfo class

• The class name of a Bean’s customizer class is determined from a
call to the getBeanDescriptor() method of the java.beans.BeanInfo
interface

• The following is the TextReaderBeanInfo.java program where the
BeanInfo class for the TextReader Bean shows how to provide
Customizer class information

import java.beans.*;

public class TextReaderBeanInfo extends SimpleBeanInfo {

// override the getBeanDescriptor method to provide a customizer.

public BeanDescriptor getBeanDescriptor() {

return( new BeanDescriptor( BeanClass, CustomizerClass ) );

private Class BeanClass = TextReader.class;

private Class CustomizerClass = TextReaderCustomizer.class; }

The TextReaderBeanInfo inherits from java.beans.SimpleBeanInfo



• The getBeanDescriptor() method is overriden

• The customizer class is postfixed with the keyword Customizer
eg. The TextReader customizer is named
TextReaderCustomizer.class

• When designing customizer classes there are two restrictions

1. The customizer class must inherit from java.awt.Component so


that it can be placed in a Panel or Dialog
18

2. The customizer class must implement the


java.beans.Customizer interface

• The customizer class is given a reference to the target component


through a call to the setObject() method
• The java.beans.Customizer interface includes functionality for
PropertyChangeListeners because the Beans container may register
itself as a listener with the customizer class

• The property updates should be followed by a call to
firePropertyChange() using the java.beans.PropertyChangeSupport
class

• The following is the TextReaderCustomizer class
public class TextReaderCustomizer extends Panel implements

Customizer {

public TextReaderCustomizer() {

setLayout( new BorderLayout() ); }

public void setObject( Object target ) {

component = (TextReader)target;

// generate the User Interface

}
public boolean handleEvent( Event event ) {

if ( event.id == Event.KEY_RELEASE && event.target == InputText )


{

String old_text = component.getInputText();

String text = InputText.getText();

component.setInputText( text );

changeAgent.firePropertyChange( "inputText", old_text, text );

}
else if ( event.id == Event.KEY_RELEASE && event.target == Width )

{
int old_width, width;

old_width = component.getWidth();
19

try {

width = Integer.parseInt( Width.getText() );

try {

component.setWidth( width );

changeAgent.firePropertyChange( "width", new Integer (

old_width ), new Integer( width )

} catch( PropertyVetoException e ) {

// wait for acceptable data.

} catch( NumberFormatException e ) {

// wait for better data.

return ( super.handleEvent( event ) );

public void addPropertyChangeListener( PropertyChangeListener l ) {

changeAgent.addPropertyChangeListener( l ); }

public void removePropertyChangeListener(PropertyChangeListener l)

{ changeAgent.removePropertyChangeListener( l ); }

private TextReader component;

private TextField InputText, Width;

private PropertyChangeSupport changeAgent = new

PropertyChangeSupport( this ); }

The handleEvent() method is called by AWT when the user enters data
20
Providing Alternative Behavior in Non-GUI Environments
• A GUI interface is not always available to a Bean especially when the

Bean is being run in the background or on a server

• Beans that need GUI in non-GUI environments can use the

java.beans.Beans class and java.beans.Visibility interface

• The static method isGuiAvailable() in the java.beans.Beans class can

be used to check whether a GUI environment is available

• The method isGuiAvailable() returns true if a GUI environment is

available to the Bean and false


• A Bean and its container can communicate about the GUI

environment by implementing the java.beans.Visibility interface

• There are four methods in java.beans.Visibility interface and they are

1. public abstract boolean avoidingGui()

2. public abstract void dontUseGui()

3. public abstract boolean needsGui()

4. public abstract void okToUseGui()

public abstract boolean avoidingGui()

• The avoidingGui() method is called by the container to check if a Bean

is currently avoiding the GUI environment

• A Bean will return true for this method if it is actively avoiding the GUI

environment

• Avoiding the GUI is different from needing the GUI

• The container can use this information to free up resources being

used by the GUI environment if a call to this method returns true

public abstract void dontUseGui()

• The method is used by the container to tell the Bean that even though
21

a GUI environment is available the Bean should not use it

A container using a Bean on a server can call this method to tell the

Bean that there is no point in using the GUI environment

public abstract boolean needsGui()

• The method is called by the container to ask whether a bean needs a

GUI environment

• If a Bean can function in a non-GUI environment it will return false

• It is safe to return true and then never use the GUI environment rather

than returning false and using it

public abstract void okToUseGui()

• The method is used by the container to tell a Bean that a GUI

environment is available and the Bean can use it

• This method might also be called after dontUseGui() to indicate that a

previously unavailable GUI environment is available again

• A call to okToUseGui() method do not implies that a Bean should use

the GUI environment if it was not planning to

Anda mungkin juga menyukai