CS 4773 Object Oriented Systems
Java Beans


This is meant to be an introduction to the concepts related to Java Beans.
Much of this comes from the Java Beans Tutorial, the JDK 1.1.5 documentation, and a set of tutorials by Dick Baldwin.
Previous Topic: GridBagLayout

Introduction
Bean Concepts
Properties and Design Patterns
Implicit Introspection
Explicit Introspection
Reflection
Serialization

Next Topic: Network Communication



Introduction

Java applets are not easily integrated into other applications. A Java Bean is a Java class that follows a specific set of interface specifications. The intention is to produce reusable software components that can be manipulated in an application builder tool.

The goal is to be able to write tools that do not have to be recompiled in order to be used. A "beans aware" builder tool maintains Beans in a pallette or toolbox. You can:

The builder tool should not need any predefined knowledge of the Bean. This allows new Beans to be added at any time.


Bean Concepts


Properties and Design Patterns

An example of a property is an instance variable whose value can be manipulated with set and get methods.

For example, a Java Label has a text field that can be set with setText and gotten with getText. Part of the reason for the many name changes between JDK 1.0 and JDK 1.1 is an attempt the follow this new naming convention. For example, the component method bounds was changed to getBounds. There is also a setBounds method.

As another example, the resize method of a component has been renamed to setSize and there is also a getSize method.

For boolean variables, instead of using a get method, an is method is used. For example, a TextComponent has a property called editable which indicates whether the text can be edited. It is set with setEditable(boolean) and tested with isEditable.

If the methods of a property are public, the property is said to be exposed.


Implicit Introspection

The Java Bean APIs contain a java.beans.Introspector class which can be used to find out about the properties, events, and methods of a class.

It can find out about properties of a bean by either an implicit or explicit method. The implicit method uses design patterns.

The Introspector creates a list of all of the public methods in the bean and searches that list for signatures that match a particular pattern.

Suppose that the following signature is found:

public void setFlavor(String f)
It will assume that the bean has a property called "flavor" and that this method is the write accessor for the property.

Here are some of the design patterns currently supported:

get/set

public PropertyType getPropertyName()
public void setPropertyName(PropertyType v)

These indicate that the Bean has a property propertyName of class PropertyType.

If either of these is detected, the introspector creates a property descriptor for the property called propertyName which is the decapitalized version of PropertyName.

is/get/set

public boolean isPropertyName()
public boolean getPropertyName()
public void setPropertyName(boolean v)

As above for boolean variable if any of these are detected.

Indexed Property Pattern

public PropertyType[] getPropertyName()
public PropertyType getPropertyName(int i)
public void setPropertyName(PropertyType[] v)
public void setPropertyName(int i, PropertyType v)

Public Method Pattern
The introspector creates method descriptors for all of the bean's public methods including all of the public methods of the bean's superclasses.

Multicast Event Set Pattern

public void addEventNameListener(EventNameListener l)
public void removeEventNameListener(EventNameListener l)

If both signatures are detected, the introspector creates an event set descriptor for an event set called eventName which is the decapitalized version of EventName.

For example, the presence of the following methods indicates that the bean fires action event sets that will be processed by ActionListeners:

   public void addActionListener(ActionListener listener)
   public void removeActionListener(ActionListener listener)

Explicit Introspection

This uses an array of package names to form a search path for locating explicit information about a Bean.

The Introspector first appends BeanInfo to the package-qualified class name of the bean and then tries to instantiate a class with that name. If this does not work it tries the search path.

If successful it eventually finds a BeanInfo for the Bean. The getBeanInfo method takes a Bean class object as a parameter and returns a BeanInfo object.

The BeanInfo class contains a number of get methods for obtaining information about a bean, such as getEventSetDescriptors which contains information about the kinds of events fired by this bean.

The getPropertyDescriptors method returns an array of PropertyDescriptor objects, each of which can be used to get information on a property of the Bean.


Reflection

Reflection enables Java code to discover information about the fields, methods, and constructors of loaded classes and to use reflected fields, methods, and constructors to operate on their underlying counterparts.

There are two types of applications that are likely to use reflection.

Example: Suppose you load a class and can find out the name (and parameter types) of a method of that class.
How would you execute the method?

More explicitly, suppose you had a variable of type MyClass and a String, MyMethod, which is the name of a method in the class MyClass. How would you execute that method?

Reflection allows you to create a reflected class from a given instance of a class. The reflected class allows you to:

One of the new classes in the Core Reflection API is the Method class. An object of the Method class provides information about and access to a single method of a class or interface.

Among the methods in the class Method are:

In addition, the Array class contains static methods that allow you to create arrays of objects of a given type.

For example, the following method is part of the Array class:
public static Object newInstance(Class componentType, int length)
creates a new array, like the creation expression:

new componentType[length]


Serialization

Object serialization supports the encoding of objects and the objects reachable from them into a stream of bytes.

It supports the complementary reconstruction of the object from the stream.

This is useful for

Objects that implement the Serializable or Externalizable interface can be written and read as in the following example:
   FileOutputStream f = new FileOutputStream("tmp");
   ObjectOutputStream s = new ObjectOutputStream(f);
   s.writeObject("Today");
   s.writeObject(new Date());
   s.flush();
Both String and Date implement Serializable.

To read these back you could use:

   FileInputStream in = new FileInputStream("tmp");
   ObjectInputStream s = new ObjectInputStream(in);
   String today = (String)s.readObject();
   Date date = (Date)s.readObject();
Object serialization is automatic for classes that implement the Serializable interface. To make an object Serializable, you need only implement Serializable, and do not need to implement any additional methods as long as all of the components are primitive or implement Serializable. Values of all fields are saved unless they are declared transient.

If you want to have control over how the object is converted to a stream of bytes, you can implement the Externalizable interface. This requires that you write the following two methods:

public void writeExternal(ObjectOutput out) throws IOException
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
One of the problems with doing this yourself is versioning. The Serializable interface takes care of problems with storing under a different version of Java than the reading.



Next topic: Network Communication