The JavaBeans Component Model
April 2002

Index: 

1  Introduction
2  Main Concepts
    2.1  Lifecycle of JavaBeans
         2.1.1 java.beans.Beans
    2.2  JavaBean basic features
         2.2.1  Properties
         2.2.2  Methods
         2.2.3  Events
         2.2.4  Naming & Binding
    2.3  Customization
         2.3.1  Introspection
         2.3.2  BeanInfo
         2.3.3  Property Editors
         2.3.4  Customizers
    2.4  Assemblies
         2.4.1 The Owner
    2.5  Contexts
         2.5.1 Hierarchies
         2.5.2 Service Provider
    2.6  Packaging
         2.6.1  Declaring JavaBeans
         2.6.2  Dependencies
         2.6.3  Design Time Only
3  Discussion on Java Beans
    3.1  What is missing ?
        3.1.1  Multiple Object Beans
        3.1.2  Versioning
        3.1.3  Packaging and Distribution
        3.1.4  Containers
    3.2 Comparing JavaBeans to other component models
4  Conclusions
5  Bibliography

1 Introduction

Components are one huge trend in software engineering today. The basic idea behind components is to build applications from reusable units that can easily be distributed. These units normally have a clear boundary (what is provided and what is required) and can allow for fine tuning through settable properties [7]. JavaBeans are one of Sun's component models and their first specification appeared on December 1996 [1]. According to it, “a JavaBean is a reusable software component that can be manipulated visually in a builder tool”. When Sun created JavaBeans, the intended goal was to "define a software component model for Java, so that third party ISVs [independent software vendor] can create and ship Java components that can be composed together into applications by end users". Since they were introduced, and thanks to the relative simplicity of the component model, JavaBeans have become popular, mostly when used to build user interfaces tools. Some people however tend to consider that the JavaBeans component model is only useful in that particular field or even that it is not a 'real' component model particularly when they compare JavaBeans to their heavyweight relatives, Enterprise JavaBeans [?] or to other component models like Corba's CCM [?]. 

The goals of this article are to make an overview of the JavaBeans component model by describing its main concepts, to discuss some of its weak points, and then to compare it briefly to other component models. The reason why this article was written is because many concepts of the component model introduced in the JavaBeans specification are often explained only through code examples, often obscuring the concepts they implement. In consequence, in this article we will try to keep implementation details to a minimum. 

The outline of this article is the following: Section 2 explains the main concepts of the JavaBeans component model, Section 3 discusses some of its limitations, and finally section 4 gives a conclusion.

2  Main Concepts

Before discussing any particular aspect of the JavaBeans component model, we must underline the fact that JavaBeans were mainly designed with visually assembly inside builder tools in mind. This particular requirement gives sense to many of the concepts of the component model.

2.1 Lifecycle of JavaBeans

One of the most important aspects of JavaBeans concerns two different 'times' or moments in which an instance of a JavaBean can exist, they are called Design-Time and Run-Time.

Design-Time makes reference to the moment when a JavaBean instance is being edited in a builder tool. To be more precise, this means that  a user is interacting with an instance of a JavaBean in the tool, possibly by setting its properties or connecting it to other instances (see fig. 1). 


fig. 1 : A JavaBean instance during Design-Time in a builder tool.

Run-Time makes reference to the moment when a JavaBean instance is running as part of an application, for example, the menu bar in the builder tool can be a JavaBean instance during run-time.

Altough in both Design Time and Run Time we refer to instances of JavaBeans, there is a big difference between them. Run-Time instances are for execution purposes only, while Design Time are a means to configure JavaBeans or to assemble applications. Furthermore, design time instances can eventually become prototypes [2] for other instances.

Once these this separation introduced, we describe with more detail the whole picture of the JavaBeans lifecycle (fig. 2).

  • Creation : when JavaBean classes are written and compiled.
  • Packaging : when one or more JavaBean classes or serialized instances (prototypes) and their satellites are stored in a Jar file along with their resources.
  • Instantiation : when an instance of a JavaBean is created either from a JavaBean class or from a prototype, this can happen either in Design Time (inside a builder tool) or in Run Time
  • Customization : when a JavaBean instance's properties are modified, during Design Time.
  • Serialization : when a JavaBean instance is stored to eventually become a prototype for other instances (if further packaged)
  • Storage as assembly: when a set of JavaBean instances are stored as an assembly.

fig.2 Different moments of the lifecycle of JavaBeans 

It is important to notice that Customization takes place during Design Time (altough it could happen at Run Time, this probably is not the original purpose). 

If an instance is customized, serialized and then packaged it becomes a prototype [2] for other JavaBean instances. This sequence of steps is very important since it provides a method to set the equivalent of class values without the need to access source code of the JavaBean and to recompile it.

2.1.1 java.beans.Beans

When instantiating a Bean, we have to cope with the eventuality of dealing with a prototype and not with an actual class. This is one of the reasons why the specification introduces the java.beans.Beans class. This class provides two important methods, the first one is a factory method that allows to instantiate the Bean and that automatically loads it either from a prototype or from a class. The second method allows to cast a Bean into a different type (see section 3.1.1 for more details).

In the following sections, the term JavaBean or Bean will make reference to a class,  the term prototype will make reference to a serialized and packaged instance of a JavaBean and finally, the term instance will make reference to an instance of a JavaBean obtained either from a JavaBean or from a prototype and .

2.2 JavaBean basic features

The three most important features of a JavaBean instance are the set of properties it exposes, the set of methods it offers, and the set of events it fires.

- Properties are discrete, named attributes of a JavaBean instance that can affect its appearance or its behaviour.

- Methods are the points of access to a JavaBean instance.

- Events provide a way for one component to notify other components that something has happened.

A JavaBean in its simplest form is simply a standard Java class that adheres to certain naming conventions in its methods. These conventions allow to express the features mentioned previously and unless a BeanInfo satellite class accompanies the JavaBean, these conventions must be followed in order to allow builder tools to discover through introspection the characteristics of the JavaBean.

2.2.1 Properties

Properties are divided into different categories: standard properties, bounded properties and constrained properties.

  • Standard properties : characterized by methods that allow to set and to get them (called setter and getter methods). Eventually, some properties can be read-only or write-only if only either setter or getter methods are present.
  • Bound properties : characterized by the fact that the Bean instance where they reside emits an event upon their modification.
  • Constrained properties : characterized by the fact that their state can only change if other Bean instances that are registered with the owner of the property agree upon its change.
Normally properties should be persistent (p. 40), to allow a JavaBean instance to become a prototype for other instances. In the specification however we find the following sentence (p. 22 - Notice that the term bean makes reference to Bean instance) : 
 
"When a bean  is made persistent it should store away appropriate parts of its internal state so that it can be resurrected later with a similar appearance and similar behaviour. [...] A bean may contain other beans, in which case it should store away these beans as part of its internal state. However a bean should not normally store away pointers to external beans (either peers or a parent container) but should rather expect these connections to be rebuilt by higher-level software. So normally it should use the “transient” keyword to mark pointers to other beans or to event listeners. In general it is a container’s responsibility to keep track of any inter-bean wiring it creates and to store and resurrect it as needed."

There is however something that may seem unclear in the above sentence, properties are characterized by setter and getter methods, and they are supposed to be persistent unless they happen to be references to other beans, in which case they must not persist. Should then other beans be considered as properties ? Or should anything that can be set or get in a JavaBean be considered another JavaBean ? (See section 2.4 ).

2.2.2 Methods

The methods a Java Bean exports are just normal Java methods which can be called from other components or from a scripting environment. By default all of a bean’s public methods will be exported, but a bean can choose to export only a subset of its public methods (See section 2.3.2)

2.2.3 Events

Events provide a way for one component to notify other components that something has happened. When a Bean generates and receives events, it follows the Observer [2] pattern. 

In case a JavaBean doesn't implement the interface that identifies it as an Observer to certain events, it is possible to interpose between it and the Bean that emits events an Adapter that can upon reception of the event call a particular method on the target JavaBean. In fact EventAdapters play a major role in the JavaBean component model, but we do not give more details about them since conceptually they have been described.

2.2.4 Naming & Binding

Bean names, like class names, must be unique within a given class loader. The names of JavaBeans should follow the naming conventions proposed by Sun. JavaBeans are distinguished not only by their name but also by the classloader that will load them

2.3 Customization

As we briefly described before, Customization is the activity of changing property values of a JavaBean instance inside of a builder tool, that is during Design Time. Since this is such an important activity in the JavaBeans component model, Sun designed several mechanisms that allow to ease the customization of bean instances. These mechanisms are:

  • Introspection.
  • BeanInfo
  • Property editors.
  • Customizers

2.3.1 Introspection

The first mechanism that allows to customize a JavaBean instance is standard Java introspection, and it is also the default one. Since the class that originated the instance normally follows certain naming conventions, a Builder tool can discover the properties of the Bean through introspection, that is by doing a run-time query on the instance of the structure of the class that originated it. By finding getter and setter methods properties are discovered, by analyzing the names of the methods event sources are found, similarly by analyzing implemented interfaces event sinks are found and finally the rest are considered standard mehods of the Bean.

2.3.2 Bean Info

An alternative possibility to describe the structure of a JavaBean is by means of a BeanInfo class. This can be seen as a 'satellite' since it is not attached directly to the JavaBean but is associated to it through a naming convention. The purspose of the BeanInfo class is to provide descriptive information about the bean to the Builder tool, in a more complex way than through simple introspection.


fig 3. BeanInfo, FeatureDescriptor and some of its subclasses

It is particularly interesting to notice that all descriptors are inherited from a base class called FeatureDescriptor which can be decorated through attributes.

It is important to mention that the JavaBeans specification defines a class named Introspector, which should be used when we want to obtain information about a JavaBean. This class will first try to locate a BeanInfo for the JavaBean and in case it doesn't find it, it will use standard introspection to generate it.

2.3.3 Property Editors

Normally after introspecting a JavaBean instance, a builder tool should provide the user some way to change the values of its properties. This may be straightforward for the so-called "basic" java types like strings, other types however may require more sophisticated ways to set their values. Property Editors were designed to solve this problem, basically they are classes that provide an editor for a particular Java type.

To allow the location of Property Editors, they can be registered in a global associating table called PropertyEditorManager that maps a Java type to a particular editor class.

2.3.4 Customizers

Normally after a builder tool introspects a JavaBean, it should provide the user with some custom way to configure it, possibly by putting together a set of property editors for all of the properties of the JavaBean. This however might be insufficient in some cases. To solve this problem, another alternative was conceived, namely that of providing a special class to allow the settings of the properties of the JavaBean is a specific way, this class is called a Customizer. Customizers are located through the BeanDescriptor class.

2.4 Assemblies

The concept of Assemblies was not treated in the original specification of JavaBeans. As we cited on section 2.2.1, the only mention that was made to connections between bean instances was that they should be "rebuilt by higher-level software".

With version 1.4 of Java, a long term persistence strategy has been introduced [4]. The persistence model is designed to handle the process of converting a graph of JavaBeans to and from a persistent form. It is important to mention that in the specification of long term persistence, the following is mentioned:
 

"All values of the properties of a JavaBean are assumed to be JavaBeans. To make this recursive definition work, we have to widen the notion of what is considered a JavaBean slightly so as to include all possible values that properties can take."
It must be noted too that event handlers itselves can also be considered as JavaBeans instances. According to this, in example of figure 4, we can count 6 instances of JavaBeans (shown highlighted).

 

<?xml version="1.0" encoding="UTF-8" ?> 
  <java version="1.3.0" class="java.beans.XMLDecoder">
    <object class="javax.swing.JPanel">
      <void method="add">
        <object class="javax.swing.JButton">
          <void property="label">
            <string>Clear</string> 
          </void>
          <void property="model">
            <void property="actionCommand">
              <string /> 
            </void>
          </void>
          <void method="addActionListener">
            <object class="java.beans.EventHandler" method="create">
              <class>java.awt.event.ActionListener</class> 
              <object id="JTextArea0" class="javax.swing.JTextArea">
                <void property="border">
                  <object class="javax.swing.border.LineBorder">
                    <object class="java.awt.Color">
                      <int>0</int> 
                      <int>0</int> 
                      <int>0</int> 
                      <int>255</int> 
                    </object>
                    <int>1</int> 
                  </object>
                </void>
              </object>
              <string>setText</string> 
              <string>source.actionCommand</string> 
            </object>
          </void>
        </object>
      </void>
      <void method="add">
        <object idref="JTextArea0" /> 
      </void>
      <void property="layout">
        <null /> 
      </void>
    </object>
  </java> 
figure 4. Example of JavaBeans assembly and its result.

2.5 Contexts

The concept of a context of execution was introduced to JavaBeans after the initial specification release [5]. BeanContexts are used basically for two different purposes : That of providing a way to traverse hierarchies of JavaBean instances, and also to provide Bean instances with a context that they can eventually query to see if it provides them particular services.


fig 5. simplified BeanContext class hierarchy

2.5.1 Hierarchies

BeanContexts follow the Composite Pattern [2], where BeanContext classes are the composites, so they allow to create hierarchies. BeanContexts contain JavaBean instances (children) and provide methods that allow to add or remove them from the context. 

2.5.2 Service Provider

Apart from a way to create hierarchies of JavaBeans instances, BeanContexts can act as service providers for the instances they host. A ServiceProvider offers through an interface a service to clients. It is interesting to note that the BeanContext model for services allows service providers to have a very dynamic behavior, being able to register and unregister int the BeanContext the services they provide at any time during execution. This philosophy can be compared to that of OSGi [6]. Since BeanContexts can form themselves hierarchies, if a JavaBeans instance requests a service on its Context, the latter might forward the request  to its own parent in case theit cannot fulfill it.

2.6 Packaging

JavaBeans and prototypes are packaged and delivered in JAR files which contains the .class, .ser and the resources for the Java Beans along with a file called the Manifest that gives information about its contents. Inside the manifest, three main aspects are treated. 

Name: org/beanome/ExampleBean.class
Java-Bean: True

Name: org/beanome/Prototype.ser
Java-Bean: True

Name: org/beanome/ExampleBeanBeanInfo.class
Depends-On: org/beanome/ExampleBean.gif
Design-Time-Only: True

Fig 6. Example of Manifest File

2.6.1 Declaring JavaBeans

Since a JAR file can contain multiple classes, the ones that correspond to JavaBeans must be identified as such. This is valid also for serialized prototypes. In figure 5, the attribute Java-Bean set to true identifies a JavaBean.

2.6.2 Dependencies

It is possible to express dependencies from a JavaBean towards files from the same JAR file. In figure 6 the Depends-On attribute allows to express a dependency between the class and an icon file.

2.6.3 Design Time Only

Classes that are "satellites" to a JavaBean and that allow to customize may be unnecessary during Run-Time. A Design-Time-Only attribute allows to identify these classes within the JAR file, so eventually they can be removed if the JavaBean is only going to be used for Run-Time purposes.

3  Discussion on Java Beans

In the last section we enumerated the main points that characterize the JavaBeans component model. As we mentioned in the introducion, JavaBeans are clearly targeted to building applications inside visual environments, and many of their features, like customization, clearly reflect that.

We will now discuss some points that are either missing or lightly treated in the original specification and we will suggest some possible way to solve them.

3.1 What is missing ?

3.1.1 Multiple Object Beans

A JavaBean as any standard Java class can extend from a parent class and implement a number of interfaces. There are however two problemes with this approach. The first one is that of the methods declared in the interfaces and all of the abstract methods of the base class must be implemented by the subclass in order to allow its instantiation. The second problem is that a class can only extend one other class, multiple inheritance is not allowed.

The initial JavaBeans specification mentions this as something that could eventually be added to the JavaBeans in a future release. It specially makes emphasis in the fact that the java.beans.Beans class must be used either when creating a JavaBeans instance and also when trying to cast a reference to the instance from one type to the other.

One possibility to provide this extension would be to use an assembly of JavaBeans as the implementation of a multi object JavaBean, some of the instances of the Assembly could be exported to form the external enveloppe of the new JavaBean.

There might be however some complexities with this approach, particularly concening customization.

3.1.2 Versioning

Currently there is not a way to specifiy the version of a JavaBean unless some annotation is used in the BeanDescriptor. Also, when instantiating a Bean, it is not possible to specify a specific version to choose. Again, the only way to make a difference between JavaBeans is by selecting a different classloader to load them.

3.1.3 Packaging and Distribution
 
 
 

3.1.4 Containers

Altough BeanContexts intoduced the concept of contexts for JavaBean instances, there is currently no concept of container in the way it exists in other component models (for example in EJB). We understand by container an object that encapsulates the actual JavaBeans instance and that interposes itself as a proxy between any client and the actual instance. Since any method call must pass by the container before actually reaching the real object, it is an ideal place where the so called non funcional aspects can be applied (for example method tracing). Since there is already a factory method available through the Beans class, it should not be very complicated to modify it so it creates proxy by means of the dynamic proxy class. The difficulty with this approach are that dynamic proxies only work with interfaces.

4 Conclusions

In this article we have done an overview of the JavaBeans component model, describing firstly all of its characteristics and then discussing some points that are poorly or not treated at all. We have underlined several times that to understand the JavaBeans component model, it is important not to forget one of the main characteristics of these components: that they can be assembled visually in a builder tool.

One issue with JavaBeans is that the specification introduces the concepts of the component model through implementation details, something that makes it more difficult to understand them. Another aspect that we think is often a source of errors in JavaBeans is that many people do JavaBeans just by following naming conventions, and tough a class like that can actually be considered a JavaBean, the prototype, customization and packaging aspects are essential if we really want to create reusable components that can be distributed.

5 Bibliography

[1] JavaBeans specification v1.0.1, Sun Microsystems, July 1997 http://java.sun.com/products/javabeans/docs/spec.html

[2] Elements of Reusable Object-Oriented Software, E. Gamma et.al., Design Patterns - Addison Wesley, 1995

[3] A Swing Architecture Overview, Amy Fowler, http://java.sun.com/products/jfc/tsc/articles/architecture/index.html

[4] XML long term persistence for Java Beans http://java.sun.com/products/jfc/tsc/articles/persistence/index.html

[5] JavaBeans Runtime Containment and Services Protocol specification V1.0, http://java.sun.com/products/javabeans/glasgow/beancontext.pdf

[6] Open Services Gateway http://www.osgi.org
 
[7] Volume II : Technical Concepts of Component-Based Software Engineering, May 2000, Technical Report CMU/SEI-2000-TR-008 http://www.sei.cmu.edu/publications/documents/00.reports/00tr008.html
 


Last update: 17 September 2002
contact: Humberto.Cervantes@imag.fr
Homepage