9.5 Improve Performance

Performance is very important to Metawidget. Whilst generating a UI dynamically - as opposed to hard coding it statically - is always likely to involve a performance tradeoff, Metawidget supports a number of techniques to help minimize this.

9.5.1 JAR Size

Metawidget has no mandatory third-party JAR dependencies and is highly modular. This allows the standard metawidget-all.jar to be repackaged for different environments to save JAR size.

For example, the addressbook-swing-applet Maven POM uses fine-grained Metawidget dependencies (as an alternative to metawidget-all.jar) to include only those modules necessary for the applet. Similarly, the addressbook-android Maven POM includes only those Android modules necessary for the Android Address Book.

Fine-grained dependencies are only available through Maven. They take advantage of Maven's dependency resolution to drag in related dependencies for you, such as org.metawidget.modules:metawidget-core. To use them, specify dependencies on a per-technology basis instead of using metawidget-all. For example:

  • org.metawidget.modules.faces:metawidget-richfaces

  • org.metawidget.modules.swing:metawidget-beansbinding

  • org.metawidet.modules:metawidget-jpa

To browse all available fine-grained dependencies visit http://repository.jboss.org/nexus/content/groups/public-jboss/org/metawidget/modules.

9.5.2 Memory Usage

All Inspectors, PropertyStyles, ActionStyles, InspectionResultProcessors, WidgetBuilders, WidgetProcessors and Layouts are immutable. This means you only need a single instance of them for your entire application. If you are using metawidget.xml then ConfigReader takes care of this for you, but if you are instantiating them yourself in Java code you should reuse instances to save memory.

9.5.3 DomInspector and DomInspectionResultProcessor

By default the Inspector and InspectionResultProcessor interfaces operate on XML strings. These are a great lowest-common-denominator, perfect for passing between disparate technologies and tiers in order to allow maximum flexibility in what can be inspected.

However, serializing to and from XML strings can be expensive. This is especially true for those Inspectors and InspectionResultProcessors that maintain their results internally in a DOM object, because the Inspector or InspectionResultProcessor must serialize its DOM to a string, whereupon the Metawidget typically deserializes it back again to a DOM.

To optimize this scenario, Inspectors and InspectionResultProcessors can optionally implement DomInspector and DomInspectionResultProcessor respectively. These interfaces allow them to expose their DOM directly, skipping the serialization/deserialization step.

If your Inspector extends BaseObjectInspector or BaseXmlInspector, this optimization is implemented for you.

9.5.4 Rebinding

For Metawidgets that do not use automatic binding, the general approach is to call setToInspect and then call setValue on each generated widget to populate values. This technique has an implicit side effect: the values can also be repopulated as many times as required from different objects, without re-calling setToInspect. This allows the Metawidget to be generated once and reused many times, mitigating the performance cost of generation.

For Metawidgets that do use automatic binding, however, setValue is never used. Setting new values requires re-calling setToInspect (and re-running generation) for every different object.

To avoid this some WidgetProcessors support a second, lightweight version of setToInspect called rebind. Using rebind, a WidgetProcessor can update the values in the generated widgets without re-running generation. This allows the Metawidget to be generated once and reused many times.

The downside of rebind is that the rebound object must have exactly the same set of property names as the original object. It becomes the responsibility of the caller to ensure this consistency.

For an example of using rebinding, see the GWT Address Book sample application.