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 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

<a id="Line017" name="Line017">017<bean class="ColorFadeBean"id="FadeBar">
</a>

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 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 tag

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

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

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

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

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:

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

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 and 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:

<a id="Line034" name="Line034">034<!-- In order to set a property of type Font, we need to construct
</a><a id="Line035" name="Line035">035            a Font object -->
</a><a id="Line036" name="Line036">036<property name="messageFont">
</a><a id="Line037" name="Line037">037 
</a><a id="Line038" name="Line038">038<!-- The font object created here will be passed to the
</a><a id="Line039" name="Line039">039              set accessor for the messageFont property -->
</a><a id="Line040" name="Line040">040         <bean class="java.awt.Font">
</a><a id="Line041" name="Line041">041         <args></a><a id="Line042" name="Line042">042           <string>Sans-Serif</string>
</a><a id="Line043" name="Line043">043           <cast class="int"><string>1</string></cast>
</a><a id="Line044" name="Line044">044           <cast class="int"><string>24</string></cast>
</a><a id="Line045" name="Line045">045         </args>
</a><a id="Line046" name="Line046">046         </bean>
</a><a id="Line047" name="Line047">047       </property>
</a>

Lines 042 to 044, enclosed within an <args> tag, specify the arguments for the Font constructor. The <cast> tags in lines 043 and 044 indicate that the strings are to be cast to int. Notice that the types of the three arguments specify the signature of the constructor; that is, they determine which constructor is to be used. Because of the types of the constructor arguments (the <args>), the Font constructor used is Font(java.lang.String, int, int).

If there are certain types that are more elegantly represented as strings (or other objects), BML allows you to write a type converter that does the conversion from the representation type (like String) to the property type. We could have written a type converter that translates the string

Sans-Serif:24:bold

to the appropriate type, but using the <args> and <cast> tags was easier. And we all know that laziness is one of the three great virtues of a programmer (the other two being impatience and hubris: see Resources below for an explanation). Now that you know how to set a bean’s properties, let’s look at how to configure what a container (like a Frame or Panel) contains.

The tag

While a <property> tag sets a bean’s properties, the <add> tag treats the object as a container, adding the enclosed objects to it. In our example, the lines

<a id="Line016" name="Line016">016<add>
</a><a id="Line017" name="Line017">017 <bean class="ColorFadeBean" id="FadeBar">
</a><a id="Line018" name="Line018">018 
</a>

and so on add the new ColorFadeBean to the Frame, which is a container.

The <add> tag hides some complexity that’s not immediately evident. Why bother having the tag, when simply mentioning a bean within another bean could cause it to be “added” by convention? Because adding an object to a container may be done in many ways. In java.util.Vector, for example, the method for adding an element is called addElement(); in AWT, it’s add().

<add> actually uses an adder registry, containing adders which handle adding an object of one type to an object of another type. The particular adder for adding an object of one class to a container object of another class determines what the <add> tag means in that context. BML tries to be completely general, so common types of addition you might want to do (such as adding AWT widgets to their containers) are handled by standard adders. But, as with the type converter registry, you can write your own adder and register it with the adder registry so that <add> will work with your types.

Let’s look at one more tag, and then we’ll discuss some of the design features and implications of BML.

The tag

Since BML was designed to be usable with all Java objects, and not just JavaBeans, it allows direct assignment of Java object fields, as well as assigning properties via the <property> tag. I don’t show an example of using the <field> tag in the ColorFade.bml sample file, because I’m a JavaBeans fundamentalist: if you want to access a component’s state, it should be done with an accessor! Reaching into an object and fiddling with its internal state by setting its fields breaks data encapsulation and makes maintaining and reimplementing software more difficult.

If the ColorFadeBean had, for example, the field

public String messageText

(which, of course, it doesn’t), that field could be set by a line something like this:

<field name="messageText" value="Rubies and Zirconia"/>

But we won’t do that, because all internal state in the JavaBean is protected, as it should be.

Sermons aside, there will often be times when you’ll want access to the internal state of an object, and the only way to do it is to access a public field. In this case, the <field> tag is your only option, making classes accessible to BML that otherwise would not be.

There’s more to the <field> tag than I’m covering here. See the BML User’s Guide, part of the BML distribution, for more details.

BML: not just for beans

The BML User’s Guide, which comes with the BML package in both PostScript and Adobe Acrobat (pdf) formats, lists BML’s design goals. Bean Markup Language is actually a misnomer, because BML will work with classes that don’t meet the (admittedly lightweight) requirements of a JavaBean. That is, BML can be used with classes that don’t implement Serializable and/or don’t have a zero-argument constructor (like the Font example above), both of which are requirements for a class to be a JavaBean.

BML is also designed to “know” as little as possible about specifics such as event types (which we’ll cover next month), data types of property and field values, and container types. Its designers deliberately created the BML framework to be extensible, so that new container types can be added to the framework and work seamlessly with the BML language.

Future work

The current implementation of BML is fascinating, and could well be a great starting place for dynamic application development. What’s more interesting than BML’s current capabilities, though, are the possibilities it opens up.

For example, the BML code mentions the possibility of using XSL to “style” XML, creating BML code that could then be used to display and manipulate the original XML. While the BML package doesn’t provide an example of this, it’s completely possible, and points to true codeless programming.

Currently, BML is written by hand. An IDE (integrated development environment) for BML would allow users to instantiate and connect components, and then serialize the results to BML format. Existing IDEs (such as IBM’s VisualAge for Java, perhaps?) could store applications in BML, and additional tools could be written to manage incremental loading of BML code at runtime.

So far, we’ve looked at how to create and configure running instances of JavaBeans, creating Java applications (albeit rather static ones) entirely in BML. Next month, we’ll look at wiring beans together with event relationships, calling methods on beans, and binding beans to scripting languages. Download BML today and start experimenting!

Mark Johnson has a BS in computer and
electrical engineering from Purdue University (1986), and has been
writing for JavaWorld since August of 1997. By day, he
works as a designer and developer for OrganicNet in Fort Collins,
CO.

Source: www.infoworld.com