Bean Markup Language, Part 1

Learn the ABCs of IBM's powerful JavaBeans connection language

IBM's alphaWorks site is a treasure trove of early-release software for Java developers. Everything on the site can be downloaded for free, although various disclaimers and restrictions apply, and IBM maintains ownership of the software. Among the many fascinating offerings from alphaWorks is BML, the Bean Markup Language. BML is similar to XML JavaBeans, the topic of a recent JavaBeans column series (see Resources), but has capabilities that XML JavaBeans doesn't even approach.

"Bean Markup Language": Read the whole series!

Because BML's outstanding documentation includes both a user's guide and a tutorial, this article will focus on what BML does, leaving experimentation to the interested reader. We'll look at the Bean Markup Language, including an explanation of the BML player and the BML compiler. BML tags will be defined by way of an illustrative example. The article will conclude with speculation about possible applications of BML that aren't touched on at IBM's site.

A wiring language for JavaBeans

BML is a language for describing structures of nested and interconnected JavaBeans. The goal of BML is to create a language that declaratively describes a structure of interconnected JavaBeans that may function together as a component, or even as a complete application. Its purpose is specifically not to create new functionality; that's what classes are for. BML provides a way to specify how components are connected to one another to perform useful tasks.

Two JavaBeans may maintain an association in one of several ways:

  • Reference -- A field or property of a JavaBean may hold a reference to another JavaBean; in other words, the value of a JavaBean's field or property is itself a JavaBean.
  • Containment -- Sometimes the value of a JavaBean field is also a JavaBean, but is not accessible from outside the bean. The bean that is the field's value can then be said to be contained by the other bean; for example, a Frame bean may contain a Panel.
  • Event binding -- One JavaBean may be an event listener for another JavaBean. When a particular event occurs, it will receive a callback from the event source with an event object.

BML provides ways to instantiate JavaBeans hierarchically, to connect them via event relationships, to assign field and property values, and to call bean methods.

BML's purpose is not to create new Java classes; rather, it is to connect instances of existing classes. To use an analogy based on electronics, if JavaBeans were software integrated circuits (components that perform specific functions), BML would be the wires and circuit-board traces that connected the components. Just as a circuit board can be used as a higher level component, itself composed of components, so can BML be used to create a new JavaBean, composed completely of lower level JavaBeans containing and/or sending events to one another.

An example from the BML tutorial appears in Figure 1. Here, we see a bee juggling three items (an eye, a bee, and an m -- get it?). On the left are the components: a frame, which contains a panel, and a panel, which contains the juggler bean (an instance of a JavaBean class), and Start and Stop button beans. The buttons are connected to the juggler bean via event listener interfaces. On the right is the application, a juggler bean with two buttons that start and stop the juggling. The components have been combined declaratively in BML, and the result is a little runnable application.

Figure 1. BML connects JavaBeans to create composite beans

BML can create and run groups of interconnected JavaBeans using either the BML player or the BML compiler. The BML player can read a BML file, dynamically instantiating and interconnecting the beans, and then executing the resulting structure. Or, the BML compiler can transform a BML file into Java code that can then be compiled and run as an application or as a new, composite JavaBean. Let's have a look at these two systems.

The BML player

Figure 2 shows a block diagram of what the BML player does.

Figure 2. The BML player turns an XML file into a collection of interconnected JavaBeans

The BML player reads the BML document using an XML parser, which converts the XML to a DOM (document object model) tree. The BML player then traverses the DOM tree, creating and interconnecting JavaBeans as specified by the tree. In the case of the example shown in Figure 2, a call to the start() method of the juggler bean appears in the BML immediately after the bean has been constructed, which starts the application. The BML player also automatically generates an event adapter for each event connection. The event adapter is a special class, generated on the fly by the BML player, which receives an event from one bean, and then calls a specified method on another bean. So, when the Stop button is pushed, the event adapter created by the BML player receives an action event. The BML code that created the event connection specifies that the result should be a call to the stop() method of the juggler bean, so the event adapter calls stop() and the juggling stops. We'll learn all about event connections next month.

Building the DOM tree and then building the resulting structure of beans results in some time overhead, particularly if the operation involves a large number of components. The BML player uses reflection to identify methods at runtime, which some programmers consider to be a performance issue. To address these concerns, the BML designers have included a BML compiler in the BML package. We'll look at that next.

The BML compiler

Figure 3 shows the BML compiler at work.

Figure 3. The BML compiler converts BML to a Java program that will run as a standalone program

The BML compiler uses an XML parser to read the XML file, converting it to a DOM tree. Instead of interpreting the tree as the BML player does, the BML compiler generates reflection-free Java source code which, when compiled with a Java compiler, results in a class file that will execute as a standalone program.

This means that entire applications can be created declaratively, and all of the code generation for the application can be generated by the compiler. This places a design burden on the software architect or designer: components must be designed so that, simply by wiring them together, all of the requirements of the application being designed are met. But this is a worthy component design goal, whether or not BML is being used.

Now that we've seen the mechanics of how BML works, let's take a look at the language itself.

BML language

BML, being an application of XML (meaning, a language defined as an XML document type definition, or DTD), consists of a set of XML tags. In this section, we'll look at what these tags do, and see examples of how they may be used.

The best way to learn BML is by using it, so that's what we'll do here. The example bean I've chosen to configure is a class called ColorFadeBean, discussed in this column in June of 1998. (See the URL for "Turn Java classes Into JavaBeans" in the Resources section below.) ColorFadeBean is useful mostly for applets. It fades a color gradient from one color to another over its entire surface, and then prints a message with customizable font, color, and alignment.

A sample BML file running in the BML player appears below.

Figure 4. The result of the sample BML script discussed in this section

Figure 4 above shows a ColorFadeBean running inside a java.awt.Frame. The frame and the bean it contains were defined in BML and executed by the BML player. The BML defines the frame, adds a ColorFadeBean to the frame, and sets the properties of the frame and the bean.

The line numbers referred to in the following text are not part of the BML, and refer to the contents of the BML source file ColorFade.bml (click the link to see the file). You may also print ColorFade.bml if you prefer. The original (unformatted) ColorFade.bml also appears in the source archives available in the Resources section at the end of this article.

Now, let's take a look at the tags in use.

The <bean> tag

The <bean> tag creates and configures a new JavaBean, or configures an existing JavaBean. <bean> is the top-level tag in a BML file.

A new JavaBean is created when the <bean> tag declares a class attribute. In the case of our example, <bean> was used in several places to create the objects in the tree. The line

004<bean class="java.awt.Frame">

creates a new bean of type java.awt.Frame. The BML inside the tag specifies the properties and contents of the object being created; that is, the new frame.

Later in the file, the line

017<bean class="ColorFadeBean"id="FadeBar">

creates the ColorFadeBean to be displayed. Notice the id attribute given to the bean. This attribute gives a name to the newly created JavaBean instance. The BML player creates the bean, and then associates it with the ID name in an object registry. The object registry is a "dictionary" that associates the JavaBeans created in BML with the names specified in the id attribute. If the attribute isn't set, the object isn't entered in the object registry.

The purpose of naming a bean is so that it can be referenced for use elsewhere. The source attribute of the <bean> tag looks up a previously registered bean in the object registry, instead of creating a new bean. If you want to create a running bean instance with the <bean> tag, and want to use the bean in several places, you name it where it's created with the id attribute. Everywhere else it's used, you specify the name in the source attribute, and the bean you created is looked up in the object registry. The object registry, along with the id and source attributes, allows creation of arbitrary networks of JavaBeans.

The <string> tag

This tag creates a string ("string beans") in a BML file. Because of how XML handles white space, creating usable strings as beans would be very difficult. <string> provides an easy shortcut for creating strings. There are two ways to specify the string's contents: either as a Text item inside of the <string> tag, like this:

042<string>Sans-Serif</string>

or using the value attribute, like this:

<string value="Sans-Serif"/>

To create an empty string, use <string/>. A string may also be given an id, which causes it to be registered in the object registry.

The <property> tag

This tag sets a property in a bean. Its value may be a string, for example:

007<property name="title" value="Color Fade Bar"/>

The property may also be of some other type, as in:

024<property name="messageColor" value="#4040ff"/>

But, wait a minute, here. "#4040ff" isn't a Color, it's a string. How is it that we can set a property whose type is java.awt.Color using a string? Because BML handles the conversion automatically by way of type converters, which are classes maintained in a type converter registry. A type converter is a class that knows how to convert objects from one type to another; for example, from String to Color, as we see above.

Several standard type converters are supplied in the BML package, and the API is also documented, so developers using BML can extend it by adding custom type converters.

Often, there will be no type converter for a property type, particularly if the property is of a class you defined yourself. Instead of requiring programmers to write type converters for every class (thereby partially defeating the purpose of BML), the designers of BML provide a way to set properties of types not easily convertible from strings. If a <property> tag doesn't have a value attribute, then whatever the <property> tag encloses is the value to be assigned. This is how the layout property of the Frame is defined:

009   <!-- Add a layout to the Frame. Notice that the type of property
010        need not be String -->
011   <property name="layout">
012   <bean class="java.awt.BorderLayout"/>
013   </property>
014   

Line 012 defines a new object of class java.awt.BorderLayout, which is then used to set the layout property of the frame. This syntax can be used anywhere that an object is needed.

Being able to construct objects of arbitrary classes like this adds a great deal of flexibility to BML, but there's still something missing: what if the object we want to construct doesn't have a constructor with zero arguments? The constructor for BorderLayout above has no arguments, so it was possible to simply create one and use it. But that's not the case with objects in general. Fortunately, BML has a solution.

The <args> and <cast> tags

The <args> tag allows creation of objects using constructors with an arbitrary number of arguments. To set the messageFont property of our ColorFadeBean, we needed a Font object. The following BML creates a Font object, and then assigns the messageFont to it:

1 2 Page 1