JavaBeans components quick tutorial

[Updated: Jan 26, 2017, Created: Sep 15, 2016]

JavaBeans specification defines reuseable software components called beans. A developer can introspect other developers bean components and can integrate them into her/his own application.

There are certain conventions that we have to follow to define a valid JavaBean component.


Beans properties and getter/setters

Beans must have a default no-arg constructor.

Getters/setters should follow the strict naming convention. If the field name is abc then the getter/setter names should be getAbc and setAbc (notice the capitalization of first letter)

It's not necessary that there has to be a field for each property. A getter can return a property value based on some local evaluation.

Also in case of read-only properties, the bean doesn't have corresponding setters.



Indexed Properties

Indexed properties are arrays or lists.



Bound Properties

A bound property notifies listeners when it's value changes

The listeners and firing event is based on the observer (or Publish-Subscribe) pattern which is used to make the components communication decoupled from direct dependencies.



Constrained Properties

A constrained property is a special kind of bound property. When a constrained property is about to change in the setter method, the VetoChangeListeners are called. Any one of the listeners has a chance to veto (reject) the change, in which case changing the property is abandoned and it remains unchanged.



Bean methods and custom events

Bean is free to define methods other than property setters/getters. Any public method that is not part of a property definition is a bean method.

A bean can fire custom events too. A custom listener must be a subclass of java.util.EventListener



The package java.beans



BeanInfo

A bean can explicitly specify which properties, events, and methods that it supports by providing a class that implements the BeanInfo interface. It exposes 'introspection information' about the bean.


java.beans.SimpleBeanInfo provides a default support implementation which contains noop (no operation) methods.

We don't need to override all the methods from SimpleBeanInfo. We can pick and choose which information we want to provide and the rest (for the one still having noop) will be obtained by automatic analysis using low-level reflection.



How to associate a BeanInfo implementation with a bean

A BeanInfo implementation name must ends with BeanInfo e.g. MyBean -> MyBeanBeanInfo

Also MyBeanBeanInfo should be in the same package location where the MyBean resides. e.g. if com.example.beans.MyBean then bean info should be com.example.beans.MyBeanBeanInfo.


What are Descriptors?

All descriptor classes in java.beans package provide some introspection information regarding their corresponding artifact.

FeatureDescriptor class is the common base class for BeanDescriptor, PropertyDescriptor, IndexPropertyDescriptor, EventSetDescriptor, ParameterDescriptor and MethodDescriptor. FeatureDescriptor supports some common information shared by all it's sub classes.

Generally methods in these sub-classes return info about :
--java.lang.Class or types defined in java.lang.reflect package.
--Some other descriptor(s) types

PropertyDescriptor has methods to create PropertyEditor as well.



What is PropertyEditor?

This interface defines methods to change text to Java objects and vice versa so that it can be used to display or edit bean properties on a UI application or some UI builder/IDE.

Typically PropertyEditor implementation is defined and registered on per Java type basis. That means one Java type will have one PropertyEditor implementation.

One bean property is associated with one instance of PropertyEditor.


How to associate a bean with its PropertyEditor implementation?

For auto discovery, the implementation of the PropertyEditor should be in the same directory as corresponding bean and should follow same naming convention as BeanInfo, e.g. if com.example.beans.ABean then the editor should be com.example.beans.ABeanEditor.



PropertyEditorManager

Provides static methods for finding and registering PropertyEditors

Finding the instance by bean type:

 PropertyEditor editor = PropertyEditorManager.findEditor(ABean.class);

Registering editor:

PropertyEditorManager.registerEditor(ABean.class, PropertyEditorImpl.class);

This overrides the editor which was auto-discovered as stated above.



PropertyEditorSupport

As PropertyEditor interface has a lot of methods to be implemented, this support class provides a default implementation. Our new editor can extend PropertyEditorSupport or we can use it as delegate.



Default PropertyEditors in JDK

JDK provides various editors by default but those are not in official API but are in com.sun.beans.editors package. Those editors are for following types: java.lang.Enum, java.awt.Color, java.awt.Font, java.lang.Boolean, java.lang.String, java.lang.Number



Introspector

This class provides standard way to get BeanInfo instance for a given Java Bean. We do that with the help of static methods of java.beans.Introspector

BeanInfo beanInfo = Introspector.getBeanInfo(ABean.class);

The target bean should follow the JavaBean conventions as described above.



Beans class

This class has static methods to instantiate a bean by it's name.

Some static methods are useful to get/set some global information, probably used in a builder or IDE environment.



Bean Persistence

To support bean persistence, our beans must implement either java.io.Serializable interface, or the java.io.Externalizable interface.

Generally, transient or static fields cannot be serialized

When using the interface Serializable, we can implement these methods with exact the same signatures to customize and control default serialization process:

    private void writeObject(java.io.ObjectOutputStream out)
                                          throws IOException;

    private void readObject(java.io.ObjectInputStream in)
                                         throws IOException, ClassNotFoundException;

When using Externalizable we can control the serialization process by implementing it's methods: readExternal and writeExternal .



Persist beans to XML format

The java.beans API provides various classes for that: XMLEncoder, XMLDecoder, PersistenceDelegate, DefaultPersistenceDelegate, Statement, Expression.

The annotation @Transient is used on the method. It indicates that the java.beans.Encoder implementations should ignore this method in encoding process if annotated with @Transient(true). This is relevant to the situation when Introspector constructs a PropertyDescriptor or EventSetDescriptor classes associated with the annotated method.

The annotation @ConstructorProperties relates the constructor parameters to the properties of beans. This information probably is useful during deserialization of immutable beans. Immutable beans are serialized using getters, they don't have any setters and Java needs to know how to initialize properties using constructor parameters during deserialization time.




Example Project

These examples demonstrate how to create/use BeanInfo, create PropertyEditor, use default PropertyEditors, analyze the target bean using Introspector etc.

Dependencies and Technologies Used :

  • JDK 1.8
  • Maven 3.0.4

Java Beans Api Example Select All Download
  • java-beans-api
    • src
      • main
        • java
          • com
            • logicbig
              • example

See Also