Introspection
Home ] Up ] What are JavaBeans? ] The Bean Development Kit ] The BeanBox ] JavaBean Properties ] Simple and Indexed Properties ] Bound Properties ] Constrained Properties ] Bean Deployment ] [ Introspection ] Property Editors ] Customizers ] Bean Persistence ] New JavaBean Features ]

 

 

How does the BeanBox, or any other similar builder tool, determine a Bean's properties, events and methods?

It does it by using introspection, implemented in the java.beans.Introspector class. The Introspector class uses the Java reflection mechanism, among other mechanisms, to gather information about the Bean.

As one wag put it:

Although Java may be reflective, even introspective, omphaloskepsis is still not part of the core distribution.

So far, in the Beans we've developed, we've used the naming conventions for getting and setting properties: methods called getPropertyName and setPropertyName, etc. 

Note: These naming conventions are inappropriately and confusingly called "design patterns" by JavaSoft.)

Sometimes, the information we supply implicitly, using such conventions, is not enough for our needs, and sometimes the reflection mechanism exposes more information than we wish.

For example, remember the SimpleScatterPlot properties sheet?

There are a number of properties that we'd rather not expose:
  • background
  • foreground

Plus, there are some properties that we would like to be displayed, that aren't exposed at all, such as:

  • points, because it is an indexed property, and its type is not displayable
  • plotBounds, because its type is not displayable

Additionally, there are times when we want to expose something about our Beans that can't be represented by the standard naming conventions.

The BeanInfo Interface

The Introspector class provides a standard way for tools to learn about the properties, events, and methods supported by a target Java Bean.

For each of these three kinds of information, the Introspector will separately analyze the Bean's class and superclasses looking for either explicit or implicit information and use that information to build a BeanInfo object that comprehensively describes the target Bean.

For each class "Foo", explicit information may be available if there exists a corresponding "FooBeanInfo" class that provides a non-null value when queried for the information. The Introspector class first looks for the BeanInfo class by taking the full package-qualified name of the target bean class and appending "BeanInfo" to form a new class name. If it fails to find this class within the classpath, then it takes the final classname component of this name, and looks for that class in each of the packages specified in the BeanInfo package search path.

Thus, for a class such as "grover.myBeans.OurButton", it would first look for a BeanInfo class called "grover.myBeans.OurButtonBeanInfo". If that fails, it would look in each package in the BeanInfo search path for an OurButtonBeanInfo class. With the default search path, this means looking for "sun.beans.infos.OurButtonBeanInfo", but the search path may be accessed and changed by the caller, using the getBeanInfoSearchPath and setBeanInfoSearchPath methods.

If a class provides explicit BeanInfo about itself then the Introspector class adds that to the BeanInfo information it obtained from analyzing any derived classes, but it regards the explicit information as being definitive for the current class and its base classes, and does not proceed any further up the superclass chain.

If the Introspector class doesn't find explicit BeanInfo on a class, it uses low-level reflection to study the methods of the class and apply standard design patterns to identify property accessors, event sources, or public methods. It then proceeds to analyze the class's superclass and add in the information from it (and possibly on up the superclass chain).

The BeanInfo Interface specifies the following methods:

Method Description
public BeanInfo[] getAdditionalBeanInfo() Returns any additional BeanInfo objects that are relevant to the associated Bean.
public BeanDescriptor getBeanDescriptor() Returns the BeanDescriptor object
public int getDefaultEventIndex() Returns the default event index
public int getDefaultPropertyIndex() Returns the default property index
public EventSetDescriptor[] getEventSetDescriptors() Returns the event set descriptors.
public Image getIcon(int iconKind) Returns the specified icon for the Bean
public MethodDescriptor[] getMethodDescriptors() Returns the method descriptors.
public PropertyDescriptor[] getPropertyDescriptors() Returns the property descriptors

It is important to note that, if you provide a BeanInfo class for your Bean, you do not have to specify everything about your Bean in it. If your BeanInfo class returns a null from any of these above methods, then the Introspector will use Reflection to provide that information for itself.

On the other hand, if you do supply some information in your own BeanInfo class, then that is considered definitive, and reflection will not be used. This can get confusing at times, if you don't understand it.

One interesting feature of the BeanInfo class is that you can associate an icon with your Bean, which can be used by a builder tool (and is used by the BeanBox) at design time.

The Default Property

It is sometimes useful, in some contexts (such as a scripting language, or similar) to define a default property. If so, the BeanInfo class can return the index of the desired default property.

The SimpleBeanInfo Class

To make things easier for you, the java.beans.SimpleBeanInfo class implements the BeanInfo interface, and provides method implementations that simply return null. This is similar to the set of event Adapter classes each of which implements its corresponding event Listener interface, and provide method implementations which do nothing. To create your BeanInfo class, you merely extend the SimpleBeanInfo class, and override what you need.

The SimpleBeanInfo class provides one additional, and useful, method:

public Image loadImage(String resourceName)

This is a utility method to help in loading icon images. It takes the name of a resource file associated with the current object's class file and loads an image object from that file. (Typically images will be GIFs.)

The SimpleBeanInfo class' implementation of the getDefaultPropertyIndex method returns -1, indicating that there is no default property.

The FeatureDescriptor Class

The FeatureDescriptor class is the common baseclass for the PropertyDescriptor, EventSetDescriptor, and MethodDescriptor classes, etc. It supports some common information that can be set and retrieved for any of the introspection descriptors.

In addition it provides an extension mechanism so that arbitrary attribute/value pairs can be associated with a design feature.

It contains the following methods:

Method Description
public Enumeration attributeNames() Returns an enumeration of the locale-independent names of any attributes that have been registered with setValue.
public String getDisplayName() Returns the localized display name for the property/method/event. This defaults to the same as its programmatic name from getName.
public String getName() Returns the programmatic name of the property/method/event
public String getShortDescription() Returns a localized short description associated with this property/method/event. This defaults to be the display name.
public Object getValue(String attributeName) Retrieve a named attribute with this feature.
public boolean isExpert() Returns true if this feature is intended for use by experts only.
The "expert" flag is used to distinguish between those features that are intended for expert users from those that are intended for normal users.
public boolean isHidden() Returns true if this feature should be hidden from human users.
The "hidden" flag is used to identify features that are intended only for tool use, and which should not be exposed to humans.
public void setDisplayName(String displayName) Sets the localized display name for the property/method/event.
public void setExpert(boolean expert) Sets the "expert" flag.
public void setHidden(boolean hidden) Sets the "hidden" flag.
public void setName(String name) Sets the programmatic name of the property/method/event.
public void setShortDescription(String text) Associates a short descriptive string with a feature. Normally these descriptive strings should be less than about 40 characters.
public void setValue(String attributeName, Object value) Associates a named attribute with this feature.

The BeanDescriptor Class

A BeanDescriptor, a subclass of FeatureDescriptor, provides global information about a Bean. It is used to desribe the classes that implement the Bean and the Bean customizer, if any.

BeanDescriptor contains the following methods, in addition to those present in FeatureDescriptor:

Method Description
public BeanDescriptor(Class beanClass, Class customizerClass) Constructs a BeanDescriptor for a bean that has a customizer.
public BeanDescriptor(Class beanClass) Constructs a BeanDescriptor for a bean that doesn't have a customizer.
public Class getBeanClass() Returns the Class object for the bean.
public Class getCustomizerClass() Returns the Class object for the bean's customizer. This may be null if the bean doesn't have a customizer.

The PropertyDescriptor Class

A PropertyDescriptor, a subclass of FeatureDescriptor, describes one property that a Java Bean exposes.

PropertyDescriptor contains the following methods, in addition to those present in FeatureDescriptor:

Method Description
public PropertyDescriptor(String propertyName, Method getter, Method setter)
throws IntrospectionException
Constructs a PropertyDescriptor, using the name of a simple property, and Method objects for reading and writing the property.
public PropertyDescriptor(String propertyName,
Class beanClass, String getterName, String setterName)
throws IntrospectionException
Constructs a PropertyDescriptor, using the name of a simple property, and method names for reading and writing the property.
public PropertyDescriptor(String propertyName,
Class beanClass)
throws IntrospectionException
Constructs a PropertyDescriptor for a property that follows the standard Java convention by having getFoo and setFoo accessor methods. Thus if the argument name is "fred", it will assume that the reader method is "getFred" and the writer method is "setFred". Note that the property name should start with a lower case character, which will be capitalized in the method names.
public Class getPropertyEditorClass() Returns any explicit PropertyEditor Class that has been registered for this property. Normally this will return null, indicating that no special editor has been registered, so the PropertyEditorManager should be used to locate a suitable PropertyEditor.
public Class getPropertyType() Returns the Java type information for the property. Note that the "Class" object may describe a built-in Java type such as "int". The result may be null if this is an indexed property that does not support non-indexed access.
This is the type that will be returned by the ReadMethod.
public Method getReadMethod() Returns the method that should be used to read the property value. May return null if the property can't be read.
public Method getWriteMethod() Returns the method that should be used to write the property value. May return null if the property can't be written.
public boolean isBound() Returns whether the property is a bound property. Updates to "bound" properties will cause a "PropertyChange" event to get fired when the property is changed.
public boolean isConstrained() Returns whether the property is a constrained property. Attempted updates to "Constrained" properties will cause a "VetoableChange" event to get fired when the property is changed.
public void setBound(boolean bound) Sets whether this property is a bound property.
public void setConstrained(boolean constrained) Sets whether this property is a constrained property.
public void setPropertyEditorClass(Class propertyEditorClass) Sets the PropertyEditor for the property.
Normally PropertyEditors will be found using the PropertyEditorManager. However, if for some reason you want to associate a particular PropertyEditor with a given property, then you can do it with this method.

The IndexedPropertyDescriptor Class

An IndexedPropertyDescriptor, subclass of PropertyDescriptor, describes a property that acts like an array and has an indexed read and/or indexed write method to access specific elements of the array. An indexed property may also provide simple non-indexed read and write methods. If these are present, they read and write arrays of the type returned by the indexed read method.

IndexedPropertyDescriptor contains the following methods, in addition to those present in PropertyDescriptor:

Method Description
public IndexedPropertyDescriptor(
String propertyName,
Method getter, Method setter,
Method indexedGetter, Method indexedSetter)
throws IntrospectionException
Constructs an IndexedPropertyDescriptor, using the name of a simple property, and Method objects for reading and writing the property.
public IndexedPropertyDescriptor(
String propertyName, Class beanClass,
String getterName, String setterName, String indexedGetterName, String indexedSetterName)
throws IntrospectionException
Constructs an IndexedPropertyDescriptor, using the name of a simple property, and method names for reading and writing the property, both indexed and non-indexed.
public IndexedPropertyDescriptor(
String propertyName, Class beanClass)
throws IntrospectionException
Constructs an IndexedPropertyDescriptor for a property that follows the standard Java conventions by having getFoo and setFoo accessor methods, for both indexed access and array access.
Thus if the argument name is "fred", it will assume that there is an indexed reader method "getFred", a non-indexed (array) reader method also called "getFred", an indexed writer method "setFred", and finally a non-indexed writer method "setFred".
public Class getIndexedPropertyType() Returns the Java Class for the indexed properties type. Note that the Class may describe a primitive Java type such as int.
This is the type that will be returned by the indexedReadMethod.
public Method getIndexedReadMethod() Returns the method that should be used to read an indexed property value. May return null if the property isn't indexed or is write-only.
public Method getIndexedWriteMethod() Returns the method that should be used to write an indexed property value. May return null if the property isn't indexed or is read-only.

The MethodDescriptor Class

A MethodDescriptor, a subclass of FeatureDescriptor, describes a particular method that a Bean supports for external access from other components.

Normally, Bean methods are exposed by making them public. The use of a method descriptor allows you to define explicitly which methods are available to be called for the Bean. It also allows you to provide more descriptive information than can be provided by low-level reflection.

MethodDescriptor contains the following methods, in addition to those present in FeatureDescriptor:

Method Description
public MethodDescriptor(Method method, ParameterDescriptor[] parameterDescriptors) Constructs a MethodDescriptor from the low-level method information and descriptive information for each of the method's parameters
public MethodDescriptor(Method method) Constructs a MethodDescriptor from the low-level method information.
public Method getMethod() Returns the low-level description of the method
public ParameterDescriptor[] getParameterDescriptors() Returns the locale-independent names of the parameters. May return a null array if the parameter names aren't known.

The EventSetDescriptor Class

An EventSetDescriptor, a subclass of FeatureDescriptor, describes a group of events that a given Java bean fires. The given group of events are all delivered as method calls on a single event listener interface, and an event listener object can be registered via a call on a registration method supplied by the event source.

EventSetDescriptor contains the following methods, in addition to those present in FeatureDescriptor:

Method Description
public EventSetDescriptor(
String eventSetName, Class listenerType, Method[] listenerMethods, Method addListenerMethod, Method removeListenerMethod)
throws IntrospectionException
Constructs an EventSetDescriptor from scratch using java.lang.reflect.Method and java.lang.Class objects.
public EventSetDescriptor(
String eventSetName, Class listenerType, MethodDescriptor[] listenerMethodDescriptors, Method addListenerMethod, Method removeListenerMethod)
throws IntrospectionException
Constructs an EventSetDescriptor from scratch using java.lang.reflect.MethodDescriptor and java.lang.Class objects.
public EventSetDescriptor(
Class sourceClass, String eventSetName, Class listenerType, String listenerMethodName)
throws IntrospectionException
Constructs an EventSetDescriptor assuming that you are following the most simple standard design pattern, where a named event "fred" is (1) delivered as a call on the single method of interface FredListener, (2) has a single argument of type FredEvent, and (3) where the FredListener may be registered with a call on an addFredListener method of the source component and removed with a call on a removeFredListener method.
public EventSetDescriptor(
Class sourceClass, String eventSetName, Class listenerType, String[] listenerMethodNames, String addListenerMethodName, String removeListenerMethodName)
throws IntrospectionException
Constructs an EventSetDescriptor from scratch using string names.
public Method getAddListenerMethod() Returns the method used to register a listener at the event source.
public MethodDescriptor[] getListenerMethodDescriptors() Returns an array of MethodDescriptor objects for the target methods within the target listener interface that will get called when events are fired.
public Method[] getListenerMethods() Returns an array of Method objects for the target methods within the target listener interface that will get called when events are fired.
public Class getListenerType() Returns the Class object for the target interface that will get invoked when the event is fired.
public Method getRemoveListenerMethod() Returns the method used to register a listener at the event source.

public boolean isInDefaultEventSet() Reports whether an event set is in the "default set".
public boolean isUnicast() Reports whether the set is unicast. Defaults to "false".
Normally event sources are multicast. However there are some exceptions that are strictly unicast.
public void setInDefaultEventSet(boolean inDefaultEventSet) Marks an event set as being in the "default" set (or not). By default this is true.
public void setUnicast(boolean unicast) Marks an event set as unicast (or not).
 
The page was last updated February 19, 2008