Short introduction to the XFormsProcessor API

For some applications it might be interesting to integrate a complete XForms implementation. This might be especially the case for fat-client applications that have complex dependencies to track in their data or have very dynamic user interfaces.

To use the core XForms implemenation a binary distribution should be used as it also contains the dependent libraries that are needed at runtime. After unpacking you find the betterFORM jar plus a subdirectory named ‘lib’ on your disk. All jar files need to be added to your classpath to enable the XForms processor.

The file ‘betterform-config.xml’ contains all configuration related to the betterFORM processor. Normally you don’t need to touch this file unless you have very specific requirements. All entries in this file have a short description.

The following example demonstrates one possibility to initialize the processor with a XForms document and to activate a trigger within that document:

  1. Config.getInstance(“file://path/to/betterform-config.xml“);
  2. XFormsProcessor xfProcessor = new XformsProcessorImpl();
  3. xfProcessor.setXForms(new URI(‘file://path/to/forms/XFormsApplication.xhtml‘));
  4. xfProcessor.setBaseURI(new URI(‘file://path/to/forms‘));
  5. xfProcessor.init();
  6. xfProcessor.dispatch(“trigger-process-data”, DOMEventNames.ACTIVATE);

Before initializing the configuration file has to be loaded (line 1). In line 2 an instance of the XFormsProcessor is created. The processor provides several setXForms methods to load a XForms document. In this case a form document is loaded via a ‘file’ URI (line 3). In line 4 the baseURI for the document is set. This is important for all URI resolutions taking place from within the XForm document e.g. resolution of <xf:instance src=“aURI“> or all submission and load URIs. All links will be resolved relative to this location unless the are absolute.

In line 5 finally the init() method is called that kicks off the processor and starts XForms processing according to the XForms spec. Finally in line 6 we simulate a user clicking a button by dispatching a DOMActivate to a trigger with id ‘trigger-process-data’.

Loading a form

There are several ways of loadiing a XForms host document into the processor. You may use one of the following methods:

setXForms(InputSource source) takes a SAX InputSource as input
setXForms(InputStream stream) Uses an InputStream which contains the XForms
setXForms(URI uri) resolves the URI and loads the result as XForms document
setXForms(Node node) Takes a DOM Node which should hold the entire XForms document.

Setting the base URI

An important step of the processor configuration is the setting of a baseURI which is used for resolving any URI used within betterFORM and the loaded XForms.

Wether you want to load a form by URI, load instance-data from external sources or execute a ‘load’ action – in all these cases the processor uses the baseURI to resolve relative pathes to absolute ones.

E.g. when running betterFORM Web the baseURI is the URI of the requested form and therefore always represented by a http url. All relative references in the form are resolved against this location meaning that a <xforms:instance src=“data/foo.xml“.../> will resolve to a http Url pointing to a subdir ‘data’ under your forms dir. The ServletAdapter sets the baseURI during init phase.

The standard procedure to set the base URI is to call:

setBaseURI(String uriString) where uriString must contain a String that parses into a URI object.

Note: please pay attention when using dynamically generated XForms which you pass directly as a DOM Node. In this case no baseURI exists and you’ve to set it manually to take care that resource resolution works.

Attaching event listeners

If you extend some Adapter or build your own you will be interested in registering eventlisteners with XFormsProcessor. The processor communicates changes to its internal DOMs by firing DOM Events at defined stages of the processing. An Adapter can register as Eventlistener (implementing org.w3c.dom.events.EventListener) and get notified of the specific changes taking place. You can register youself as listener for all eventtypes defined in XForms 1.1. Please refer to chapter 4 ‘Processing Model’ of the XForms 1.0 recommendation for details (http://www.w3.org/TR/2003/REC-xforms-20031014/slice4.html).

betterFORM defines some additional non-standard events which make life easier for an Adapter implementor. To see what currently supported you should study the source of de.betterform.xml.xforms.events.EventFactory along with the javadocs.

To be able to process the events from the processor your Adapter must:

  1. implement org.w3c.dom.events.EventListener by providing a handleEvent method
  2. call addEventListener to attach yourself as listener for a specific eventtype when starting processing.
  3. Call removeEventListener to cleanup when you stop listening (normally during shutdown). This is IMPORTANT cause otherwise you’ll likely produce leaks.

Initializing the processor

hat one is easy. After you’ve setup the processor simply call:

xfProcessor.init()

That’s all.