Thursday, November 17, 2011

More resilient error handling in XForms

What should your application do when a error occurs?

One approach is to let the application crash and burn (errors are not supposed to happen, right?). This behavior remains typical of many "native" (C/Objective-C/C++) desktop and mobile applications. Your only hope is that the app has some kind of autosave feature, or you have lost your work.

On the other hand, some applications are more resilient. For example, Java-based apps like the IntelliJ IDE nicely warn you that something wrong occurred but try their best to stay up. Some web applications also try to recover from JavaScript errors. More often that not the error is not fatal, your data is not lost, and you can even continue working as if nothing had happened. This is made easier with languages that use exception handling.

Now the XForms spec takes kind of a tough stance on this. For certain errors (like referring to the wrong model or bind by id, or an error in an XPath expression), the expected behavior is to "halt processing", and this is not even cancelable by the application author.

This behavior is perfectly fine if those errors are found as the app is initializing: in that case, you haven't had a chance to interact with the app and enter data, so typically nothing is lost.

But if those errors occur later, after you have already spent minutes typing in information, the "crash and burn" approach is going to be a source of frustration.

To alleviate this, an "autosave" feature is a great option, and we hope to add this to Form Runner in the future. But what else can be done? Well, break out of the XForms requirement to halt processing is one thing.

And that's exactly what we have done recently: Orbeon Forms now has the ability to recover from many runtime errors. Recovery has a few aspects:

  1. Defaulting to default values. Example: a control binding using an XPath expression failing at runtime binds to the XPath empty sequence, in effect making the control hidden.
  2. Not producing any result at all. Example: a value calculated using an XPath expression failing at runtime is ignored.
  3. Interrupting processing locally. Example: an action encountering an error stops, but further events and user actions are allowed to proceed.

In all those cases, errors are logged so the developer can be informed and take action. By default, the user also sees an error dialog, which can be dismissed so that further actions, such as saving data, can be attempted.

We think that this change is good for both users and programmers, and we hope that XForms 2 will standardize some of this behavior.

For more details, see the documentation for this feature.


  1. "More often that not the error is not fatal, your data is not lost, and you can even continue working as if nothing had happened." Nope, nope, nope.
    The current XForms behaviour is well thought out.
    By attempting to handle exceptions you risk saving corrupted data, a much bigger problem than the user 'losing their work'.
    If the user is losing more than an hours work that would be surprising, saving corrupted data could take days to recover from. Fail hard, fail early!

  2. Tim,

    Fail early, sure, when you can. After all, there is no point in running an application you know is broken from the start. This is why Orbeon Forms, for example, analyzes most XPath expressions upon page load, and won't let the page run if errors are found at that time.

    Fail hard: yes, if you can fail early; no, if, if you can't fail early, because we think that the quality of the user experience here is more important. If the XForms engine halts processing, there is absolutely nothing you can do in XForms to help the user.

    Now please realize that the new behavior *allows* you to write your application to let a user to save data even after an error. It does not force you to do that. Errors throw events, and you can decide to consider those events fatal, or to specifically prevent further saving, or to save your data marked with an autosave flag. Further, validation of the data might also take place at the service/database level.

    Where we think XForms is absolutely not well thought-out here is that dynamic errors are *necessarily* fatal. Form author should instead be able to make an informed decision about what to do when that kind of error occurs.