HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Ever since it was announced in May of 1996, Java Beans has been a topic of great interest among Java developers. The first generation Java technology embodied several modern software engineering concepts such as object-orientation, platform independence, multithreading, network awareness, etc. However, it lacked a few important elements, including support for visual assembly of software components, object persistence and distributed computing. Java Beans is the next generation Java technology that not only adds the functionality it lacked but also makes Java programs more portable and interoperable with a number of component models that include Microsoft's ActiveX/COM, Netscapes's LiveConnect and IBM's OpenDoc.

At the time this article was written, the Java Beans 1.0 specification[2] had been released and JavaBeansª is slated for release in the first quarter of 1997[4]. This article provides an overview of Java Beans, focusing mainly on the programming aspects and leaving aside the hype. It is mostly based on the Java Beans draft specification and other related documents[1,3,4] published by JavaSoft.

What is Java Beans?
As per the draft white paper[1], Java Beans is a software component architecture that enables creation, assembly and use of dynamic Java software components. A software component is a reusable software module that is supplied in a binary form. Interface to the component is at a binary level. A component is like an IC (Integrated Circuit) which can be "plugged" into an application and "wired" to other components. Just like the ICs, components created in different environments can be wired together to build applications. A software component that conforms to Java Beans APIs is simply called a bean.

Central to Java Beans is a set of APIs called Beans APIs. Supporting the Beans APIs are a number of new Java features which include Reflections, Object Serialization, AWT Enhancements, Inner Classes, RMI, IDL, etc. The new JDK 1.1 will include the implementation of the above features. These features address the following key industry needs:

Component Creation and Visual Assembly
In the traditional application development approach, software components are created and assembled by manually coding. For example, user interfaces in Java are created by using the AWT class libraries. While creating user interfaces, every time a component needs to be added programmers will write code to set the properties and to invoke appropriate event handling methods. As programmers can not visualize the user interface immediately, a tedious trial and error process of code-compile-run is often employed to achieve a desirable look. Moreover, every time a component is created, uninteresting and repetitive code will have to be written.

In view of this, what is desirable is an interactive environment to put the components together and to automatically generate skeleton and repetitive code for the components. Microsoft's Visual Basic and Borland's Delphi are two such popular environments in the PC world. In an application builder's environment, programmers can pick a component from the "toolbox" containing a pallet of icons, move it to a container and lay it out along with other components through the use of a pointing device such as a mouse. The application builder will also generate code for the components. It will also provide a way to insert code for event handling. Visual programming thus allows programmers to visually compose applications using already developed software components. It enables rapid prototyping and rapid application development(RAD). Java Beans APIs provide full support for component creation and their visual assembly. Application builder tools can be built using these APIs.

Distributed Computing
With the current Java technology, it is not possible for a Java program to invoke methods in different machines. An applet, for instance, is downloaded into a machine and executed locally. It is often required to run some tasks locally and some remotely for a variety of reasons. A computer may not have required resources or sufficient memory and/or computing power to perform a task. For example, computing intensive tasks such as 3D model generation requires high performance computers. The low-performance client computer can invoke methods in remote high performing computer and receive only the results. Distributed computing also helps to balance the computing load between different machines.

Figure 1

There are three packages that enable distributed computing. These are RMI, IDL and JDBC. The new Remote Method Invocation (RMI) package enables the method invocation from one Java machine to another. The Java IDL package enables the remote invocation of methods in CORBA objects using the Interface Definition Language(IDL). Thus, the RMI package enables a bean to interact with another Java Virtual Machine and the IDL package with a non-Java environment. The JDBC APIs let a bean access the database in a local as well as remote database server.

Portability and Interoperability
A Java program currently may run in different containers such as Netscape Navigator, Microsoft Internet Explorer, etc., but it can not interact with their environments. For example, an applet in a Netscape container cannot interact directly with other applets. One of the primary goals of Java Beans is to make a bean not only run on a wide variety of containers but also interact with other objects in their respective environments. This type of interaction is achieved by building bridges to various component models. The component models currently targeted for bridging are: Netscape's Live Connect, IBM's OpenDoc and Microsoft's ActiveX/COM. The details regarding the component model bridges were still sketchy at the time this article was written. JavaSoft will provide an ActiveX bridge which will provide connectivity between Java Beans APIs and COM. Work is also underway at Netscape to create a bridge to JavaScriptªand LiveConnectª and at IBM/Apple to create a bridge to OpenDoc.

Bean Characteristics
Publishing and Discovery
A bean is made up of a set of .class files and is accessed through its publicly accessible interfaces. It has two lives - one in an application builder and the other in a live application. In order for a bean to be customized and connected with other beans, the application builder will analyze the bean to discover its public interfaces. There is a need. therefore. to introspect a bean to learn about the public fields, methods, events, etc., using its .class files. The Beans APIs provide mechanisms to introspect and customize beans. The Beans APIs make use of the new Core Reflection APIs which provide separate classes for Class, Method and Field. These APIs will also help vendors to develop their own property editors and customizers and allow them to insert information about the public interfaces. Thus, a bean at design time may be associated with several vendor-developed classes, providing a lot of information about the bean. If information is not provided, the introspection mechanism in the Beans APIs will extract the default information using the .class files.

Events
A bean can fire as well as capture events. Whenever a desired event occurs, one or more beans may have to be notified for providing an appropriate response. The current event model is AWT centric and in many respects inadequate for visual programming. The new delegation model is generic and solves a number of problems that are prevalent in the old model. More details are provided in a subsequent section.

Persistence
A running bean can be preserved as an object with its internal states intact by an object serialization mechanism. It can be restored to the same state by deserialization. Whether it is a build or runtime environment, it is often required to save and retrieve objects. For example, when a component is brought into an application builder and made to run so that the developer can modify its appearance and behavior. Once satisfied with the customization, the developer may want to save the component as it is. JDK 1.1 provides the Object Serialization mechanism to store and retrieve objects with their internal states intact.

Visibility
A bean can be visible, nonvisible or both. Here are some examples. The AWT button is a visible component. A timer bean can be a nonvisible component. An image loader can be used as a visible bean on the client side and as an invisible bean on the server side. Even if a bean is nonvisible, it can be associated with an icon to identify it on a builder tool.

Internationalization
A bean may have a lot of locale-dependent aspects which are typical to region and/or language. For example, label names, messages (status and error), currency names, measurement systems. In order for a bean to be used internationally, JDK 1.1 provides the Internationalization feature which enables a bean to be developed independent of languages (natural) and regions and then localized to suit a language and/or a region.

Properties
A bean's appearance and behavior is determined by its properties. A property can be a simple primitive data type or a complex class. The application builder can edit the properties using the property sheet. A property is a Java data type and is associated with an editor. In the case of a simple and known property, the application builder itself will provide the editor. In the case of a custom written property, the vendor will have to provide the editor. The Beans APIs provide mechanisms to supply the property editors along with the beans.

Property Types
A property can be simple or indexed. The simple property is single valued and indexed property is multiple valued (i.e., it can have a set of values). A property also can be bound and/or constrained. A bound property is tied to another property in the same bean or in other beans. A constrained property is the one which is not allowed to be changed under certain conditions. The Beans APIs provide two event handling mechanisms to notify the changes to the bound and constrained properties.

Consider the example of an Image Viewer bean which contains two beans: Viewport and Annotation. The Viewport bean displays images on a view port and the Annotation bean contains the text (example: name of the image and viewing parameters)which is to be superimposed over the image. The properties of Viewport bean are width, height and the starting position of the annotation. The properties of the Annotation bean are font, font size, width and height. In order for the size of annotation text to be proportional to the size of the view port, the font size of the annotation text needs to be changed whenever the width and height of the view port are changed. Thus, the Viewport width and height are bound properties. In the same manner, the starting position of the annotation can be a constrained property. It may depend on the width and height of both the Viewport and Annotation objects. The Annotation bean can veto the change in the start position property if it determined that the text may overflow the view port.

Design Patterns
In order for the application builder tools to access the bean public interfaces, properties and methods need to follow certain patterns called design patterns. For example, properties have to be accessed by get and set types of methods. Some of the design patterns for properties are: get<property> and set<property>.

Events
Irrespective of whether they are visible or nonvisible, beans can fire events. The current event model is inadequate for supporting Java Beans. Currently, event generation and event handling are available in the AWT only. This means that a visible component is needed to handle events.

The Current Event Model
The current event model is based on the principle of inheritance and propagation. All the events types are defined in a single class called Event. The AWT component class provides several event handling methods. The mouse and keyboard events are received by using the event specific methods such as mouseDown(), mouseDrag(), keyPress(), etc. Action events are typically fired by the GUI components like buttons and are received by action() methods. In addition to the above event-specific methods, the AWT Components class has the handleEvent() method which receives all the events. If handleEvent() is overridden by a component, then the mouse, keyboard and action events are received by the handleEvent() method only, not by the event methods. This is a cause for confusion.

If a complex GUI container is to be developed, it will have a handleEvent() method with a large number of conditional statements which typically check the type of event and the kind of component receiving the event. Events are propagated along the GUI hierarchy, i.e.; from child to parent. This is achieved by returning a boolean value from the event handling method. It is often necessary to subclass the component just to receive events. While being simple, the current event model thus does not lend itself to good object-oriented design. Furthermore, a component receives all the events irrespective of whether it requires them or not. In other words, there is no way to filter events. The unnecessary event traffic results in reduced performance.

Figure 2

The New Event Model
The new event handling scheme in JDK 1.1 is designed to overcome some of the above drawbacks. The Event class is replaced by a hierarchy of event classes, each of which correspond to a type of event. The EventObject class is the root of the events tree and resides under the java.util package. Unlike in the current model, this would enable a nonvisible bean to fire events.

A new event model, called the Delegation Model, has been proposed. In this model, events are propagated from a "Source" object to one or more "Listener" objects. An event can be an object instantiated from a class extended from the EventObject class. When an event occurs, the source object generates such an event object and sends it to the registered listener objects. The EventListener interface in the java.util package is the root of the event listener interface tree. The listener class implements an appropriate listener interface. In order to receive event notification, listener objects have to register with the source object. Thus, selected events are delivered to the interested parties only.

AWT Event Handling
Since it can be anticipated that the majority of beans that fire an event are visual, the AWT has implemented the new delegation model. In the AWT events hierarchy, there are two categories of events: Low-level and Semantic.

Low-Level Events:
Low-level events are tied to a physical device such as keyboard and mouse. The list of low-level event classes is as follows:

  1. ComponentEvent
  2. FocusEvent
  3. InputKeyEvent
  4. MouseEvent
  5. WindowEvent
Semantic Events
Semantic events are not tied to a specific device or a component, but are defined by behavior, such as action, adjustment and item selection. The list of semantic event classes is as follows.
  1. ActionEvent
  2. AdjustmentEvent
  3. ItemEvent.

Listeners
Each event type has one or more Listener interfaces. For example, there are two Listener interfaces for mouse events. These are: MouseListener and MouseMotionListener. The MouseListener listens to mouse clicks, i.e., mouse up or mouse down and has corresponding methods. Similarly, the MouseMotionListener listens to mouse movements, i.e., mouse drag and moves, and has the corresponding methods.

Figure 3

Adapters
The object that is expected to receive an event can implement the relevant Listener interface and register with the source for receiving events. But, objects often receive the same types of events from different sources. How do you know which object is firing the event? Again, we may end up with several conditional statements. An alternate way would be to have intermediate classes called Adapters which will receive events from a given component and direct them appropriately.

For each of the low-level Listener interfaces in the AWT, default implementation of the adapter class is available. The class that receives the events can extend the predefined Adapter class and override only those methods that the application is interested in.

Figure 4

Since a component knows what types of listeners are registered, the toolkit can generate and deliver only events corresponding to those listeners, thus reducing the event traffic. The Adapter classes also remove the need to subclass components to receive events.

Listing 1 is an example of an ImageViewer application. It has a command panel with two buttons: DisplayImage and Quit. The actionPerformed() method is the ActionListener interface method and is invoked when a button is clicked. As you can see from the code, events are not handled in the container CommandPanel and there is no need to extend the button to handle events.

Delegation model benefits:

  1. GUI and Application separation
  2. Reduction in event traffic resulting in improved performance.
  3. Event handling methods will not have numerous conditional statements.
  4. In line with Java design, method pointers were avoided.
  5. There is no need to extend a class only for handling events.

Problems

  1. Complicated compared to the old model
  2. A complex UI may end up with a large number of adapter classes.
  3. The listener interface may have several methods, each representing an event. Even if an object is not interested in receiving all the events, it will still get them. For example, the mouseMotionListener interface has two methods - mouseMoved and mouseDragged. The Listener that implements this interface will not only have to implement both the methods but also will receive both the events. This problem can be solved to some extent by extending the MouseMotionAdapter class. But still, both the events are fired. While it is an improvement over the old model, it still is a problem in terms of event flow.
Reflection APIs
The Reflection APIs are the new core APIs that are added to JDK 1.1. They are comprised of several new classes and some methods that are added to the class Class. The Reflection APIs can be used for providing runtime access to the public fields, methods and constructors of a class. Runtime access is essential for application builder tools to discover the attributes and public interfaces of a bean. These APIs use the accessed public members. For example, a method that has been accessed can be invoked provided the security policies permit that operation.

The following are the three important Reflection classes.

  1. Field - Important Methods: getDecalringClass, getModifiers, set and get.
  2. Method - Important Methods: getDeclaringClass, getModifiers, getReturnType, getParameterTypes, getExceptionTypes and invoke.
  3. Constructor - Important Methods: getDeclaringClass, getModifiers, getParameterTypes, getExceptionTypes and newInstance.
The above classes will reside under the package java.lang.reflect. Some of the new methods in the class Class are getFields, getMethods, getConstructors. These methods will return an array of corresponding members in a class represented by the Class object. These include all the inherited members as well. If you need only the members of a particular object, then use the getDeclaredFields, getDeclaredMethods and getConstructors. The Reflection APIs are expected to be used by the application builder tools.

Beans APIs
Beans APIs are a set of APIs that allow application builders to inspect classes and customize components. These APIs reside under the package java.beans. The Beans APIs provide three different beans related functionality which are: Introspection, Customization and Property Change Notification.

Introspection
Introspection is a mechanism through which the application builder tool analyzes a bean and learn about its public interfaces. The introspection mechanism provides two ways to accomplish the runtime discovery of a bean's public interfaces. These are:

  1. Using the low-level Reflection APIs
  2. Using the vendor provided explicit information.

The Introspector class will provide the application builder with the BeanInfo class. Example: BeanInfo myBeanInfo = Introspector.getBeanInfo(beanClass, stopClass)

Introspection can take place on all of the classes that start from beanClass and move up on the chain until it reaches the stopClass. Each bean class can be associated with a BeanInfo class which will provide information on the bean and its properties, methods and events. The naming convention for BeanIfo class is <classname>+"BeanInfo" . If a bean class is not provided with a BeanInfo class, Introspector will provide the default BeanInfo object.

The Beans APIs also contain a set of descriptor classes. These include BeanDescriptor, EventsetDescriptor, PropertyDescriptor and MethodDescriptor. The BeanInfo class has a get method for each of the descriptors. PropertyDescriptor[] myBeanPropertyDescriptor = mybeanInfo.getPropertyDescriptors()

A vendor can choose to provide explicit information on only a selected set of descriptors. The descriptor classes have a super class called FeatureDescriptor. Each descriptor class has a number of constructors for creating the corresponding descriptor objetcs. The bean vendor can provide the descriptor information here by overriding some of the methods.

Customization
A bean can be customized to suit the end users application. The simplest way to achieve this is to provide a property sheet in which the user selects a property and edits its value. Since not all beans are simple, customization can involve complex operations. Component vendors in such cases may provide elaborate customization software which would guide an user through the entire process. Each Java type needs a property editor the complexity of which may vary widely. The component vendors can also provide property editors for any new data types defined.

The PropertyEditor interface has the methods that are to be implemented by a custom editor. The editor can reside along with the bean or in the application builder. In order to locate the editor, the Java Beans provides the PropertyEditorManager class. Custom editors can register with this class or have a class follow the naming convention <classname>+"Editor". The PropertyEditorManager will look for it in the appropriate places in the Java package hierarchy.

Property Change Notification
A bean can fire a property change event whenever a bound or constrained property is changed. In accordance with the new event model, the objects that are interested in receiving property change events will have to register with the source bean.

The Beans APIs have the PropertyChangeEvent class for creating both the bound and constrained property change events. The corresponding listener interfaces, PropertyChangeListener and VetoableChangeListener, have methods to enable event transmission. In addition, there are two utility classes: PropertyChangeSupport and Vetoable-ChangeSupport, which can be subclassed or instantiated. A bean that has the bound or constrained property can have instances of these two classes as member fields. The other classes can register and "unregister" for a property change by listening through these member fields.

Packaging Beans
As we already know, a bean is a set of class files. Associated with beans sometimes are resource files such as images, sounds, messages, etc. The new JAR technology enables the storage of beans and associated resources. A JAR file is a ZIP format archive file. A vendor can put several beans in a JAR file and ship it. These beans can share the resource files. The bean can also contain the serialized prototypes of beans. The Beans class in Beans API will enable direct instantiation of beans from the serialized prototypes.

Creating Your Own Bean
What does it take to build a bean?. Here are the steps to building a bean:

  1. Develop the component programs and create the corresponding .class files. The properties, events and public methods in the class files should conform to the specified design patterns. If a bean is to be preserved in a serialized sate, provide the serialized files (.ser files).
  2. Develop design time classes
    1. BeanInfo class: A light weight bean does not need a BeanInfo class. A custom written BeanInfo class would help the developer understand the structure and behavior of the bean better.
    2. Customizer: Again, a property sheet will suffice to customize a simple bean. A complicated bean requires a customizer to guide the user to adjust the attributes and behavior.
    3. Design time classes will not be a part of the actual component when it is running inside an application.
  3. Gather all the required resources. Images, audio, video and message files are some examples of resources.
  4. Create HTML-style files documentation.
  5. If it is used internationally, provide locale-dependent files for resource file and documenation
  6. Package the bean in a JAR file.

As you can see from the list, a bean builder need not go through all the steps. A light bean may go through only steps1 and 6.

Class Libraries Vs Beans
A class library [5] is a collection of related classes. Class libraries are often built for the purpose of solving problems in a particular domain. For example, data compression class libraries may include implementation of several data compression algorithms. Programmers need the actual documentation to discover the interfaces to a class library. Applications are created by interweaving the class library APIs. Class libraries thus offer a lot of flexibility.

Beans, on the other hand, are typically self contained and developed for the purpose of performing specific tasks. Beans are bundled with the necessary class files and resources and can be executed independently. While the appearance and behavior of a bean can be changed, its structure is fixed.They behave like pre-fabricated blocks. A bean's granularity can vary from a simple component to a huge application.

Compared to beans, class libraries are general in nature. A class library may have more than one method to accomplish a functionality. A functionality can be easily extended by sub-classing and overriding. It may also have additional methods for debugging. Class libraries often provide partial solutions in order to generate intermediate results. Developers thus have more freedom to design applications using class libraries. Beans typically provide full solutions. For example, the data compression vendor may supply several compression beans such as JPEG compressor, Wavelet compressor, etc. These beans may even include GUIs to control the quality of compression. Beans are ideal when tasks are specific and there are clear cut inputs ands outputs. Beans, of course, have all the advantages of visual assembly.

Conclusions
Java Beans technology is the next big step for Java technology. It is at the center of many exciting things that are happening in the Java world. Java Beans and related APIs have introduced a number of new computing paradigms to Java and carry its motto "Write Once, Run Everywhere" to a higher level by providing interaction with different component models. If all the promises are kept, Java Beans should deliver the best of many worlds.

References

  1. Javaª Beans - Component APIs for Java, July 1996, Sun MicroSystems.
  2. Javaª Beans 1.0 API Specification, 10 Oct 1996, JavaBeans Web page, JavaSoft.
  3. JDK 1.1 Preview, Java Web page, JavaSoft.
  4. Nov 6th Developers Conference Slides, Java Beans Web page, JavaSoft.
  5. L Rodrigues, "Build Your Own Class Libraries," a chapter in Professional Java Fundamentals by Wrox Press, Sept. 1996.

About the Author
Lawrence Rodrigues is a senior consultant with Compuware Corp., Milwaukee, and is co-author of the book, "Professional Java Fundamentals" published by Wrox Press. The author can be reached at [email protected]

	

Listing 1: An event handling example.

     public class ImageViewer
           public void   displayImage( ) { // Appropriate code }
           public void   quit() { //  Appropriate code}
                         // Other methods
           static public void main(String args[] ){
             CommandPanel cmdPanel = new CommandPanel(this);
}
}

	// Adapter class for Display Image button
               
    class DisplayCommand implements ActionListener {
            public  DisplayCommand (ImageViewer viewer){
                       viewer = vw;
}
            public void actionPerformed(ActionEvent e){
                      viewer.displayImage();
                     }
               }
              
              //Adapter class for Quit button

              class QuitCommand implements {
                      public QuitCommand(ImageViewer vw){
                                viewer = vw;
                      }
                     public void actionPerformed(ActionEvent e){
                                viewer.quit();
                     }
             }
// The command panel GUI is created here

class CommadPanel {
       public CommandPanel(ImageViewer viewer){
            DisplayCommand  dispCmd = new DisplayCommand(viewer);
	       QuitCommand  quitCmd = new QuitCommand(viewer);
             Button displayBtn = new Button('Display Image');
               Button quitBtn = new Button('Quit');
              displayBtn .addActionListener(dispCmd);
                                  quitBtn.addActionListener(quitCmd);
                     Frame cmdFrame  = new Frame();
                      cmdFrame.setLayout(new FlowLayout());
                                  cmdFrame.add(displayBtn);
                                  cmdFrame.add(quitBtn);
                                  cmdFrame.pack();
                                  cmdFrame.show();
                       }
                }

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.