GWT 2.1 Editors

GWT 2.1 is advertized as providing "a framework for business apps", and one of the included features is the Editor framework, which provides data binding between bean-like objects and UI fields.

The Basics

On one hand you have an object graph that you want to display or edit, and on the other hand a set of widgets (let's call them editors, we'll see the why later). To use them together so that your objects are displayed in the editors, you'll use an editor driver.

GWT 2.1 comes with two editor drivers: the SimpleBeanEditorDriver and the RequestFactoryEditorDriver. Similarly to UiBinder, you'll declare an interface extending one of these with generic parameters.

The kind of objects that you can edit depends on the editor driver you use, but in any case they'll be bean-like objects. SimpleBeanEditorDriver edits any simple Java bean while RequestFactoryEditorDriver expects only RequestFactory proxies; and in case that's not enough (really?), it's technically possible to create your own editor driver flavor (and it's not that much work, though you have to be familiar with the editor framework internals).

Finally, editors are any class that implement the Editor marker-interface or the IsEditor interface. There are further constraints and features, and that's the whole point of this article, as we'll see below.

Editor drivers

Both editor driver interfaces have two generic parameters: the type of the object being displayed or edited (I'll always use edited from now on, but editors can be read-only, and thus only display data), and the type of the root editor.

The GWT Editor framework makes extensive use of code generation. Because everything is done at compile-time by inspecting classes, it means everything is based on the types you use in your interface declaration (and for sub-editors, see below, the field and method declarations). If you then use the generated code on a subclass of the editor for instance, only the bits inherited (and possibly overridden) from the declared editor type.

The Editor framework uses a Flow Synchronization pattern: you edit an object for the editor driver to populate editors from the object's values, and you later flush the editor driver to copy editors' values back into the edited object. During a flush, editors have an opportunity to report errors that will be available as EditorErrors.

The SimpleBeanEditorDriver provides just that: an edit() method, a flush() method, and a pair of hasErrors() and getErrors() accessors. But before you edit() an object, you'll first have to initialize() the editor driver with the actual editor instance to be used.

We'll look at the RequestFactoryEditorDriver later.

Editors

Editors are a graph of objects used to edit objects. Each editor is bound to a type of object that it can edit. Starting from a root editor type, the editor driver generator will build a representation of the editors tree using reflection: any non-private field or non-private no-args method whose (return) type is an editor will be seen as a sub-editor, unless it is annotated with @Ignore. The name of the edited property will be infered from the field or method name (it will be field/method name after an optional Editor suffix has been removed), unless it is annotated with @Path (which can use the dotted notation to reference a sub-property; in GWT 2.2 you'll also be able to use the empty string to reference the current object). At runtime, if any of these sub-editors is null, it will simply be ignored. This is known as the Editor contract.

A field or method will be treated as an editor if its type implements the Editor marker interface (or one of its subinterfaces, see below) or the IsEditor interface. There are several kinds of editors:

Editors can also implement a couple of other interfaces to extend their behavior:

Most widgets displaying or editing values are already editors (most are actually IsEditors of editor adapters): TextBox, Label, DateBox, CheckBox, etc. and a few widgets have been added to add type specialization: IntegerBox, DoubleBox, NumberLabel, DateLabel, etc. This makes the Editor framework a very good friend of UiBinder!

Integration with RequestFactory

The RequestFactoryEditorDriver is similar to the SimpleBeanEditorDriver but with a few key differences:

Conclusion

The GWT Editor framework is a real time-saver, because you no longer have to maintain the code to push your objects' properties into widgets and back to the objects, and you therefore no longer have to test that code (because as soon as you add a field, you'll probably copy/paste lines and can miss a change, injecting a property into the wrong field, or a field's value into the wrong property). As a proof of that, I've quickly drafted a before/after sample (only files that are necessary to understand the code are included, and I know there are typos and missing imports, but using this user script or Chrome extension you can then easily see a diff between the 2 versions)