Categories
frameworks

Growing Frameworks: Beans

What are beans?

Bean rules

Beans as plugins

What are beans?

Java Beans are software components. From the Java Beans specification: “A Java Bean is a reusable software component that can be manipulated visually  in a builder tool.” The goal of this is to encourage a split in software development: some developers will build components; others will hook them together to build applications.

Beans work like this:
The bean developer:

  • defines the component
  • defines design-time tools to view or configure the bean

The bean user (application developer):

  • obtains the packaged bean
  • loads it into the builder tool
  • specifies (usually by drag-and-drop) the instances of the bean
  • customizes each instance
  • hooks them to other beans
  • generates the application

The end user:

  • couldn’t care less

What’s good about beans?

  • concrete functional implementation
  • etc.
What’s bad about beans?
·         etc.
Beans vs. frameworks:
The bean box is oriented toward construction (black-box components). Frameworks may be black-box, white-box, or something in between. Frameworks implement applications by writing code; bean box by wiring components.

Building a Bean

A minimal bean has few constraints:
·         Provide a no-argument constructor
·         Implement Serializable (or Externalizable)
·         Follow bean naming conventions

Java Beans as a Black Box Framework

“A Java Bean is a reusable software component that can be manipulated visually in a builder tool.”  Java Beans 1.01 specification.
Java Beans:
                Definition
                Requirements – thread-safe
                Using a beanbox
                Events
Event model sidebar
Bean vs class library
Design vs runtime
Serializable, Component
Properties, Methods, Events
Properties: bound & constrained
JAR file with manifest

Sidebar: Class, Abstract Class, Interface

In object-oriented programming, an object is usually thought of as having basic data and methods to operate on the data, with inheritance from parent classes.
This book encourages the use of interfaces. In Java, an interface consists of method declarations only: no class data (except constants), and no implementation.
                Interface
The definition is like this:
      public interface MyInterface {
            public void doSomething();
            public void setValue(int);
            public int getValue();
      }
Because it says nothing about data or implementation, it provides a strong dependency barrier: an object accessed through an interface can only call the methods; it does not have direct access to the class data.
A normal object can declare data:
      public class MyObject {
            private String name;
            public void setName(String name) { this.name = name;}
            public String getName() { return name;}
      }
Note that each method includes an implementation.
[Just show code for each variation: interface, subinterface, class, abstract class, abstract class with abstract method, extends, implements, multiple implements]

Beans

1. Requirements
                Threadsafe
                Serializable or Externalizable
                Naming conventions
                Component
2. Properties
                get/set
                Indexed
                Bound
                Constrained
                (Both)
3. Methods
                public
4. Events
                EventListener
                Unicast/Multicast
5. Introspection / Design Info vs runtime / “Design patterns” and introspection
                BeanInfo
                Customizer
6. Packaging
                JAR files

JavaBeans

Java Beans are black-box components. A visual tool (known generically as a beanbox) provides mechanisms to hook up events and properties. Beans have three things of interest: methods, properties, and events.
A method is a normal object method with public access. The bean box usually provides a means by which property changes or events can cause methods to be called. (Some beanboxes are very limited, and only support methods with no arguments.)
Properties are the “data” associated with a bean. Users don’t have direct access as they would with public data in a class. Instead, access is through a routine, so the “data” can be created at will by the routine. For example, the background color of a component might be a property.
When objects are wired together in a beanbox, events represent the “electricity.” Actions are triggered because events happen. For example, hitting “Return” in a textfield might cause an event.

A JavaBean has few requirements:
* it must be thread-safe
* It must implement Serializable (or Externalizable) so it can be saved
* it should follow naming conventions (or provide a design tool) so its methods, properties, and events can be discovered.
* it should inherit (directly or indirectly) from java.awt.Component if it wants to be visible.
* it should have an empty constructor
A bean is stored either as a .class file or a .ser file, contained in a JAR file with a manifest declaring its bean nature. A beanbox knows how to deal with beans in either of these forms.
[SIDEBAR: JDK 1.1 Event Handling  TBD]

Properties

Properties come in four types: simple, indexed, bound, and constrained.
Simple properties are just values associated with the bean. For example, the background color of a component might be a simple property. (The BDK – bean development kit from Sun – only supports well-known types such as int, String, or Color.) Properties will be shown on the “property sheet” – a structure listing the properties and their values.
Indexed properties allow for array-like properties. An example might be a list of supported types.
Bound properties are where things get interesting. When a simple property changes, the value changes, and that’s that. When a bound property changes, there may be listeners who are notified of the value change.
A constrained property also has listeners. Instead of just changing, the constrained property asks listeners if they would like to veto the change. (If any listener vetos, the value is changed back.) A constrained property is usually bound as well. A window might use this mechanism: when someone attempts to close it, the vetoers are given a chance to forbid it unless changes are saved.

Events

JavaBean events are mostly the same as events in the JDK 1.1 event model. An event is an indication that something has happened. For example, a Button has an ActionEvent that tells when it has been pushed.
An object defines the events it generates, and it manages the list of listeners who should be notified when the event takes place. The listeners can then take whatever action they deem appropriate.
Events give JavaBeans a data-flow-like feel: an event can trigger a series of other events, each propagating information to other objects.

Hooking Things Up

                [color chip]
                                setR
                                setG
                                setB
                                getColor
                Gray 0-255 slider  <—->  setValue(ChangeEvent e)
                Query String   [Find button]   Display
                  (eg URL)

Knowing the Bean

The beanbox needs some mechanism to tell it the methods, properties, and events of the bean. There are three methods it uses:
* introspection, reflection, and naming conventions
* BeanInfo
* BeanCustomizer
The simplest method is by use of naming conventions. (This is sometimes referred to as “design patterns” in the beans documentation, but that use of the term is so far from what we’re calling design patterns that we’ll stick with the more accurate term.) The idea is that you name your methods a certain way, and the beanbox can match the names against the naming conventions. For example, if you have “public Color getColor()”, it can deduce that you have a readable property named “color” of type Color. If you have a method “public void addActionListener(ActionEvent e)”, you are regarded as a generator of ActionEvents. The beanbox can discover your method names by reflection – see java.lang.Class and java.lang.reflect.* to see how this can work.
From methods matching the naming conventions, the beanbox can build a “property list” of all the properties, and an event list of all available events. The beanbox can use this information to allow you to connect events to objects.
[Table – naming conventions  TBD]
The second mechanism is by use of a BeanInfo class. If you provide both MyBean and MyBeanBeanInfo, the Beaninfo is asked for the class description. The BeanInfo can choose which properties and events to expose. Once the information is obtained, it looks just like the naming conventions approach.
The final mechanism is a BeanCustomizer. A customizer is an object that takes responsibility for setting the values of a bean. It need not follow the “properties” approach at all. For instance, it could have a whole series of dialogs used to customize the final bean.
Note that BeanInfo and customizers are needed only at design time. The bean itself may be much smaller than they are.

How it works – implementing a beanbox

Let’s look at the steps a beanbox uses to create an application.
Locating beans: The beanbox provides some means of locating jar files containing beans. This could be a dialog box, default directory, etc. The beanbox can look at the jar file to find the bean’s class, and a BeanInfo or customizer class if available. Given these, the beanbox can create the bean information it needs: locate properties, methods, and events.
Creating a bean: The bean’s empty constructor can be used to create an instance of the bean. (See java.lang.Class.newInstance().) The properties (or the customizer) can be used to set the bean’s values. A representation of the bean can be placed on the screen.
Hooking up events:  This is where things get interesting. The easy case is when the source object generates SourceEvents, and the target is a SourceListener. Then you can see that “source.addSourceListener(target);” will work.
The more interesting case comes when two beans don’t have any knowledge of each other’s events.
                Source                                                            Target
      addSourceListener()        doSomething()
      removeSourceListener()
We can’t add Target directly to Source. Instead, we’ll introduce a (hidden) adapter class. It will conform to the source on one side, and the target on the other.
      SourceTargetAdapter implements SourceListener {
            Target target;
            public void sourceHappened(SourceEvent e) {
                  target.doSomething();
            }
            public SourceTargetAdapter(Target t) { target = t;}
      }
This object can be added to the Source as a SourceListener, and it will call the Target.
Where does this adapter come from? The beanbox can generate the code, and arrange for it to be compiled into a class file.

Creating an Application:  Once everything is designed, the beanbox can generate an application. It knows which beans have been used, so it creates a serialized instance of each. It generates code to arrange for the components to be hooked together as they were in the beanbox. It packages them into a JAR file so you have an applet or application ready to run.
Running the generated application:  The final result looks like a regular application as far as the JVM is concerned, and runs like any other.

Black-Box Design for Beans

Event orientation
Adapters
Supply of beans
Importance of adapter and decorator
Composition