The JavaBeans
Component Model
April 2002 |
Index:
|
"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 ).
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)
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.
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
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:
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.
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.
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.
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." |
<?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> |
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
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.
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.
Name: org/beanome/ExampleBean.class Java-Bean: True Name: org/beanome/Prototype.ser Name: org/beanome/ExampleBeanBeanInfo.class |
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.
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.
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.
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.
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.
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
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.
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.
[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
|