Test-driving XForms with Orbeon

In this second installment, we conclude our evaluation of XForms implementations and explain why we ultimately preferred the Orbeon engine. I walk you through a XForms sample to explain essential concepts. My team has spent quite a lot of time understanding the Orbeon architecture and I discuss our findings, including separate-deployment configuration and state handling.

When we did our first research on XForms, we tried out many different implementations (see last post). It became very soon clear to me that it would be the best to start with a server-side engine, because this approach allows a seamless integration in existing applications. Because all processing is done on the server side, the engine always delivers regular HTML to the browser. Therefore, server-side engines work without a plug-in on the client side, i.e. they look and feel like a standard Struts or JSF application. (Orbeon runs on Firefox, IE (6, 7, 8), Safari, Google Chrome, and Opera.) Also, as the engine runs in the same environment as our existing JEE applications, technical integration is much easier.

There were only two relevant choices: Orbeon and Chiba. In the end, Orbeon turned out as the winner. But at first, Chiba looked very promising, due to its simple architecture, small codebase and it’s also easy to operate! Orbeon, on the other side, appeared quite complex – a monolithic, 40 MB web archive (WAR); also it seemed a challenge to integrate it into existing Java EE applications (more about how we solved this below).

Why we chose Orbeon

In the end, we chose Orbeon, because our primary goal was to gain experience with the XForms technology. And unlike Chiba, Orbeon supports almost all of the XForms 1.1 features. The Orbeon community is very active and the core developers are also regularly answering questions in the Orbeon mailing list.

In my opinion, the only drawback of Orbeon is it’s complexity. It took us weeks to understand how to configure and integrate Orbeon. And it probably takes months to fully understand all of its features like processors, pipelines or XBL components. And if you need a certain feature which Orbeon lacks, you’re probably stuck because of the complexity of the code-base (except you’re willing to pay the creators of Orbeon for customization).

Here are the four finalists, just in case you are evaluating XForms engines, too:

  • Orbeon: The XForms we finally chose for your XForms projects.
  • Chiba: The only engine comparable to Orbeon. Supports far less XForms features. Also further development seemed to have stopped in 2008.
    Update: The betterFORM XForms engine is a successor of Chiba and seems really interesting. See also the comments below.
  • Mozilla XForms Plug-in / IE Forms Player: Quite usable but as browser plug-ins require installation on the client
  • EMC XForms Engine: Very promising pure JavaScript solution (GWT), but still lacks some important features (most importantly internationalized date and currency fields!).

Overview of the Orbeon Architecture

As described on the Orbeon website: Orbeon is a server-side, Ajax-based XForms implementation. Server-side means, the XForms engine runs on the server side and the state of the XForms GUI controls is also held on the server side. This leads to a user experience similar to common Java web frameworks like Wicket and JSF. Ajax-based means that the Orbeon engine transforms an XForms XHTML document into a view that can be displayed by a regular web browser, e.g. regular HTML plus JavaScript callback code. The transformed view is then displayed by the client (web browser). When the user submits the form, the data is sent back as a HTML-form POST request and is processed by the Orbeon engine.

The architecure of Orbeon. The engine transforms XForms documents (produced by the application) for regular web browsers.

Our Sample Form

Let’s start our test-drive and produce a working XForms document. I’ve picked an sample form that we implemented within a day. It’s simple but already uses many of the nice features of XForms.

The form is part of a bank account application process and is used to enter basic personal data about the applicant. The enumeration values (gender, title, etc.) are read from separate XML resources. Some fields are only visible, if a certain checkbox is checked (e.g. address changed within last three years).

Our sample XForms form.

When developing XForms documents, the first step is usually to define the XML data structure containing the information to be display and edited upon. The reason for this is that XForms reads all data from XML. Editing data with XForms means retrieving an XML document from a URL, changing it and sending the result to an URL.

Here is an example of a pre-filled XML document for our form:

<?xml version="1.0" encoding="UTF-8"?>
<Kreditkartenantrag
  xmlns="http://www.mgm-tp.com/xforms-showcase/">
  <Kunde>
    <Geschlecht>M</Geschlecht>
    <Titel>Dr.</Titel>
    <NamensVorsatz>zu</NamensVorsatz>
    <NamensZusatz>Hause</NamensZusatz>
    <Nachname>Mustermann</Nachname>
    <Vorname>Max</Vorname>
    <Geburtsname>Beispiel</Geburtsname>
    <Adresse>
      <Strasse>Standardstrasse</Strasse>
      <Hausnummer>15</Hausnummer>
      <PLZ>80815</PLZ>
      <Ort>Teststadt</Ort>
    </Adresse>
    <Geburtsdatum>2001-01-01</Geburtsdatum>
    <Geburtsort>Teststadt</Geburtsort>
    <Familienstand>ledig</Familienstand>
  </Kunde>
  <Adressaenderung3Jahre>true</Adressaenderung3Jahre>
  <BisherigeAdresse>
    <Strasse>Alte Standardstrasse</Strasse>
    <Hausnummer>11</Hausnummer>
    <PLZ>80811</PLZ>
    <Ort>Testdorf</Ort>
  </BisherigeAdresse>
  <Taetigkeit>
    <Beschaeftigungsart>Rentner(in)</Beschaeftigungsart>
    <Berufsbezeichnung>Musterjob</Berufsbezeichnung>
    <BeschaeftigungSeit>2001-01-01</BeschaeftigungSeit>
    <MonatsNettoEinkommen>5000</MonatsNettoEinkommen>
  </Taetigkeit>
  <Kontakt>...</Kontakt>
  <SchufaUebermittlung>...</SchufaUebermittlung>
  <Ausweis>...</Ausweis>
  <KreditkartenKonfiguration>...</KreditkartenKonfiguration>
  <UnterschriftLiegtVor>true</UnterschriftLiegtVor>
</Kreditkartenantrag>

If you compare the XML document with the visual representation of the XForms document, you might notice, that the structure of the XML document differs from the XForms document:

  • The nesting and naming of the elements in the XML document is different, e.g. in the XML document, all address attributes are grouped in one “Adresse” element. In the XForms document, the attributes are further subdivided (Straße / Hausnummer, PLZ / Ort).
  • The document contains typed / non-text elements, e.g. the date of birth is stored in ISO date format “yyyy-dd-mm”, whereas the XForm displays the date formatted as “d.m.yyyy”. This is very important to allow internationalization of the form and standardized processing of the XML document.
  • Some elements of the XML document do not appear in the form at all. The reason could be, that these elements are edited in other forms or the XML structure is also used in other contexts than XForms.
  • The document contains a reference to an XML schema. This schema is used to validate submitted form data.

A Walkthrough of our sample XForms

Now let’s have a look at some interesting parts of the form code.

The schema attribute of the model element allows us to point the XForms processor to an XML Schema definition:

<xf:model schema="/documents/kreditkartenantrag.xsd">

Next come the references to XML documents containing actual data:

<!-- Default instance -->
<!-- Form data to be displayed and edited upon -->
<xf:instance id="antrag"
			 src="/documents/kreditkartenantrag.xml" />

<!-- List of employment types -->
<xf:instance id="employmentTypes"
			 src="/enumerations/employmentTypes.xml" />

The first XML document we reference here automatically becomes the default instance, i.e. the document we refer to when we define our input controls later. All other instances in this example refer to enumerations used for radio buttons and select boxes.

Next comes the submission element. It tells XForms, which data should be sent back to the server when the form is submitted:

<!-- example submission action with validation disabled -->
<xf:submission id="submission" ref="instance('antrag')"
			   validate="false" replace="all"
			   resource="/xforms/REST/post.jsp"
			   method="post"  />

The last part of the XForms model structure is the bind element:

<!-- former address is only asked for if address has changed within
the last three years -->
<xf:bind nodeset="/d:Kreditkartenantrag/d:BisherigeAdresse"
         relevant="string(../d:Adressaenderung3Jahre)='true'" />

This bind elemend shows one of the coolest features in XForms. It binds the relevant attribute of the default instqnce element for “former address” to the value of the element for “address changed within last three years”.

In XForms, input controls bound to elements with “relevant == false” are hidden. So this bind rule has the effect, that the input controls associated with the “former address” element are only visible when “address changed within last three years” is true. In summary, it’s a declarative way of showing / hiding input controls depending on a boolean expression.

The XForms group element is used to define an XPath context for contained input controls. This allows to use relative XPath expressions inside the group. The group itself is rendered as an HTML span. The group’s class attribute is copied 1:1 to the resulting span and styled with CSS to create a two column layout.

<xf:group ref="/d:Kreditkartenantrag" class="first column">

The rest of the document contains the XForms input controls, embedded into a few HTML elements for layout purposes. Here are some random excerpts:

<span class="table-row">
  <xf:input ref="d:Nachname">
    <xf:label>Nachname</xf:label>
  </xf:input>
</span>
...
<span class="table-row">
 <xf:label class="table-layout-header">Beruf</xf:label>
 <xf:select1
		ref="d:Taetigkeit/d:Beschaeftigungsart"
		appearance="minimal">
   <xf:label>Art der Beschäftigung</xf:label>
   <xf:itemset nodeset="instance('employmentTypes')/item">
     <xf:label ref="@name" />
     <xf:value ref="@value" />
   </xf:itemset>
 </xf:select1>
<span/>

Finally, the button for submission of the form is described as follows:

<xf:submit submission="submission">
  <xf:label>Formular absenden</xf:label>
</xf:submit>

This submit element refers to the submission definition with ID “submission” I have shown above.

Integrating Orbeon with a Web Application

Because with XForms you only build web forms (and not complete web applications), Orbeon is normally integrated into an existing application. One configuration which we evaluated at mgm is a standard Servlet-based web application combined with a separately deployed instance of the Orbeon engine. This form of operation is official described in “Using the Orbeon Forms XForms Engine with Java Applications“.

In the separate deployment scenario, a Tomcat server contains two web applications:

  • Business application: containing all pages of your application as well as the XForms.
  • Orbeon application: Orbeon deployed as a separate web application.

Our business application handles all “normal” page requests. The pages can be regular HTML or XForms/XHTML pages. In case of JSP, we use a custom JSP tag to include the XForms content into the JSP, producing the XForms pages. Our custom JSP tag (source code here for download.) is very similar to <jsp:include>.

Now, how are the two web applications connected? Our application is configured with a special Servlet filter, OrbeonXFormsFilter. This filter processes all requests to XForms pages (which have an extension like “.xhtml”). The Servlet filter then communicates with the Orbeon application through a RequestDispatcher.

Illustration of how we integrated Orbeon and our business application in the separate deployment configuration.

This configuration results in a relatively loose coupling of the business application and the Orbeon XForms processor. The regular Orbeon distribution can be used (with a few additional configurations, see the file “properties-local.xml” below). For server-side integration, I had to implemented a small JSP tag which fixed a problem with the Servlet response buffer handling in Orbeon’s XFormsFilter.

Our XForms document is seamlessly integrated into the regular web pages of the business application. The rendered HTML can be styled with CSS.

Downloads

Other Features of the Orbeon Engine

Integration with Backend Systems – One aspect I did not mention is the integration of the form with middleware / backend systems. I simply assumed that all data is read from and written as XML over HTTP (which is quite nice because it allows to write XForms before the server side logic is implemented). Possible approaches for XML include custom XML parsing (e.g. JDOM) or XML to Java binding (e.g. JAXB). The resources can be implemented as plain Servlets, JSP pages or (more conveniently) through the new JEE 6 REST API (JAX-RS).

Another topic which quickly arises are custom XForms controls. Many applications have special requirements for some controls, e.g. a specific date picker or input control for monetary amounts is required. Orbeon provides XBL for this, see for example Guide to Using and Writing XBL Components.

State Handling – A weak spot of Orbeon (and server side form processing technologies in general) are response times and server load. Because the form state is kept on the server side, whenever the form state changes, a round trip is required. Orbeon provides some configuration parameters to suppress round trips for unused events (e.g. DOM focus events). To reduce the memory consumption on the server, the form state can be kept on the client (see
Orbeon XForms – State Handling).

Share

Leave a Reply

*

5 Responses to “Test-driving XForms with Orbeon”

  1. Joern Turner says:

    Hello,
    what a pitty you missed the betterFORM XForms engine which is a successor of the (now stalled) Chiba project. betterFORM builds directly on the shoulders of Chiba butis man-years ahead of it especially regarding the XForms 1.1 conformity.

    betterFORM was launched officially early this year and already has quite some active users and and a responsive mailinglist.

    Joern

  2. Hi Joern,

    I just had a look at betterFORM and it really looks promising. I will definitely evaluate it in detail!

    Baschir

  3. Wade English says:

    Great post! I’m interested in the custom JSP tag that you had to write for including Orbeon forms in your JSPs. Would it be possible to share the code?

  4. Jean-Baptiste Pressac says:

    Hello,
    Thank you for this feedback. However, where didi you placed the kreditkartenantrag.xsd and complex-form.xhtml files ? In fact, Orbeon has a Form Builder, but I guess you did not used it ?