ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

What's the Matter with JMatter?
Pages: 1, 2, 3, 4

Developing the Entire Model


Let's take a look at the listing for the implementation of the type Speaker.

The first thing to notice are the basic members of Speaker: name, bio, and photo.

   private final StringEO name = new StringEO();
   private final TextEO bio = new TextEO();
   private final ImgEO photo = new ImgEO();

Name is a string type. The field bio, on the other hand, is marked as a TextEO, which signals to the framework that we want to use a text area for its user interface representation, and a large text field to persist the information (that a varchar(255) won't do). Finally we can store blobs right along other fields. The photo field is of type ImgEO. JMatter provides editors and renderers for many basic types (as well as formatters, parsers, and validators for zip codes, dates, SSNs, and more), and they can all be customized if necessary. For each member field we supply a getter method.

The two other members have one-to-many relationships: talks and speaker recognitions (e.g., a speaker is both a JavaOne rock star and a Java champion).

   private final RelationalList talks = new RelationalList(Talk.class);
   public static Class talksType = Talk.class;
   public static String talksInverseFieldName = "speaker";

   private final RelationalList recognitions = new RelationalList(SpeakerRecognition.class);
   public static Class recognitionsType = SpeakerRecognition.class;

For one-to-many associations, we use the JMatter RelationalList list type. There's also a slight wrinkle here in that we're required to provide a way for JMatter to statically infer the list item type. That's the reason for the metafields talksType and recognitionsType. If defining a bidirectional relationship (that is, if Talk points back to speaker), we signify this with another meta-field (talksInverseFieldName), again helping JMatter knit it all together.

Here's some optional metadata for controlling the field display order in the user interface:

   public static String[] fieldOrder = {"name", "recognitions", "talks"};
   public static String[] tabViews = {"photo", "bio"};

The metafield tavViews specifies that the fields photo and bio should be displayed in separate tabs.

Finally, here's another interesting customization:

   private transient PhotoIconAssistant assistant = new PhotoIconAssistant(this, photo);
   public Icon iconLg() { return assistant.iconLg(); }
   public Icon iconSm() { return assistant.iconSm(); }

Here we're overriding the two methods that control which icon to use for this instance. Since we have a photo field with a picture of the speaker, a per-instance icon based on the speaker's photo is even better than a generic speaker icon. The class PhotoIconAssistant makes sure that we use the speaker's photo only if one is provided. It also makes sure to provide versions of the photo scaled to the appropriate size.

Here's the listing for the class SpeakerRecognition.

We've identified two possible recognitions: Java rock star and Java champion. Each has its own unique icon in the brochure. So let's model this type simply with two fields: name and icon. Again, we want to use the icon as a per-instance icon, overriding whatever default icon is supplied for this type.


Let's take a look at the implementation for the class Room.

Two fields are defined: the room name, and its capacity (an IntEO).

This class illustrates one feature we haven't yet seen: the ability to initialize some values by overriding the initialize() method:

   public void initialize()
The talk type hierarchy

Next, let's look at the implementation for the base class Talk.

We define a talk topic, span (e.g., from 11:00 a.m. to 11:45 a.m.), and description. There are also one-to-one associations to the talk's speaker and location (room). We setup the default duration for talks to 45 minutes, and supply the necessary accessor methods.

Unlike our other type definition that extends AbstractComplexEObject, this class extends the JMatter class CalEvent. By subclassing CalEvent we specify that talks are events that can show up in a calendar. As such, they must bear a TimeSpan-type field, which we do through the field span, and which JMatter dynamically locates.

A future version of JMatter will likely automatically know to expose a calendar view for the type Talk, simply by virtue that Talks bear a field of type TimeSpan, without requiring the subclassing of CalEvent. We're trying to be a little more duck-typed.

JMatter has a second, more sophisticated version of calendaring that supports viewing events in multiple locations side by side on the same day view, with strong support for drag and drop. The Sympster demo application which is bundled with JMatter, is an illustration of this version. In it, dropping a talk onto a day view of a calendar automatically creates a Session at the designated time and location. Dragging the view of the session from one column to another automatically updates the talk's location. It's a very visual way of manipulating information.

Now to define the three specializations of Talk: Keynotes, Technical Sessions, and BOFs. Keynote is the simplest as it requires essentially no specialization.

The next one, BOF, adds the field code (e.g., BOF-2344) and the corresponding accessor. We also mark the code field as unique through the identities metafield.

   private final StringEO code = new StringEO();
   public StringEO getCode() { return code; }

   public static String[] identities = {"code"};

For tech sessions, which are more structured, we need to supply the track for the talk and a talk level such as beginner, intermediate, etc. (Here is the listing)

Finally, the TalkLevel type is very similar to how we modeled a Track. It's very simple. JMatter recently defined a new annotation: @EditWithCombo, that customizes the editor in a field context to make it easier to pick.

   public class TalkLevel extends AbstractComplexEObject
Putting it together

We typically don't build anything linearly. I developed this sample application over a couple of sessions, iteratively. However, it's difficult to relay the experience in writing.

It's easier to understand how all this works and how the pieces fit together when we start dealing with examples; let's stop talking about types and start looking at instances.

This time around, rather than customize the classbar from the user interface, let's edit the file class-list.xml directly.

To run our application, we must first export the schema and then invoke the run target:

  ant schema-export
  ant run

Rather than fill this article with screenshots, I went ahead and recorded a screencast of a session with our JavaOneMgr application.

Our base application, the JavaOneMgr, consists in its entirety of less than 500 lines of source code. This metric illustrates some of the leverage that JMatter affords developers.

There's much that can be built on top of this base application. Some use cases include:

  • Extending the model to include attendees and allowing them to manage their personalized schedule.
  • Adding the ability to register for talks. Such behavior can ensure that the room's capacity is not exceeded before registering an attendee.
  • Printing summary reports of all talks, organized by track. Perhaps JasperReports can be used on top of the basic application to design and produce the report. At a lower level, iText can come in handy to produce PDFs.

Exposing custom behavior into the application is very simple and straightforward, by defining a method marked with the @Cmd annotation.

There are many more features to this framework than we have space for in this article. Here are a few features of JMatter that we did not discuss:

  • Built-in validation support
  • A sub-framework for constructing wizards
  • Support for objects with states

JMatter also automates the production of your Java Web Start war file. Please refer to Chapter 15 in JMatter's manual for the details.

Let's switch gears and discuss how this project has evolved during the last year.

Pages: 1, 2, 3, 4

Next Pagearrow