Comments? Feedback?

This wiki does not yet support public comments (a limitation of Google Sites), so we encourage you to post your comments on Twitter by responding to @orbeon.

Recent site activity

XForms - Asynchronous Submissions

Rationale

  • Asynchronous submissions are specified in XForms 1.1.
  • There are interesting use cases for them, including:
    • Background autosave
    • Background loading of initial data from multiple services

Implementation status

As of July 2009, Orbeon Forms implements a subset of XForms 1.1 asynchronous submissions.

More precisely, Orbeon Forms currently does not allow an asynchronous submission with side-effects (such as replacing an instance, or dispatching events after a response is received) to run after an HTTP response has been sent to the client. This means that either:
  •  The submission must have no side-effect ("fire-and-forget" submission):
    • It must have replace="none"
    • It doesn't fire xforms-submit-done or xforms-submit-error
  • The submission must terminate in the scope of the current HTTP request, that is before the request returns to the browser
    • In this case it can have replace="instance" or replace="text"
    • In this case it fires xforms-submit-done or xforms-submit-error
While XForms 1.1 specifies that mode="asynchronous" should be the default, in Orbeon Forms mode="asynchronous" is the default.

Fire-and-forget submission

This is enabled for a submission with mode="asynchronous" and replace="none", e.g.:

<xforms:submission id="autosave" mode="asynchronous" ref="instance('document')" method="post"
    resource="http://my.server.com/autosave"
replace="none"/>

Processing

  • The submission runs after the client HTTP request that triggered the submission has returned a response to the client.
  • If there are multiple such fire-and-forget submissions, they run sequentially.

Limitations

  • Fire-and-forget submissions do not truly run in the background. Instead they run sequentially at the end of processing.
  • Optimized submissions do not yet support the asynchronous mode.

Background submissions

This is enabled for a submission with mode="asynchronous" and replace="instance" or replace="text", e.g.:

<xforms:submission id="call-service" mode="asynchronous"
    method="get" resource="http://www.orbeon.com/ops/xforms-sandbox/service/zip-states"
    serialization="none" xxforms:cache="true"
    replace="instance" targetref="instance('zip-states')"/>

This is useful for example to speed up the initial load of data from slow services when the page initializes because the background submissions can run in parallel, and at the same time the page can pursue its own initialization.

Processing

  • A new background submission is initiated
  • The background submission
    • executes the request (http:, https, oxf: and file: are supported)
    • deserializes the response if needed
      • for instance replacement, creates an XML document (read-only or read-write)
      • for text replacement, reads the text content as a String
  • The server waits for background submissions to terminate
    • If the client request that triggered the submission is a regular page request, it waits until all the xforms-ready events have been processed.
    • If the client request that triggered the submission is an Ajax request, it waits until all the events have been processed.
  • The result of each background submission is processed as soon as available. This includes instance replacement, text replacement, and firing xforms-submit-done / xforms-submit-error.
  • If processing background submissions causes new background submissions to run, their results are processed in turn.
  • The client request returns to the client. 
NOTE: If the resulting instance is cacheable with xxforms:cache="true" and already in cache, it is immediately retrieved and no background submission takes place.

The xxforms:join-submission action

This extension action allows waiting until all background submissions have been processed:

<xforms:action ev:event="xforms-model-construct-done">
    <xforms:send submission="query-people"/>
    <xforms:send submission="query-places"/>
    <xxforms:join-submissions/>
</xforms:action>

In this example, upon xforms-model-construct-done, two background submissions are started. For performance reasons, it might be a good idea to wait until they terminate before allowing the controls to initialize. The <xxforms:join-submissions> action waits until they have all completed. If processing background submissions causes new background submissions to run, their results are processed in turn.

Limitations

  • Optimized submissions do not yet support the asynchronous mode.
  • replace="all" is not supported

Implementation notes

Fire-and-forget submissions

  • In this case, Orbeon Forms does not create a new thread, but it uses the current Ajax request thread (for simplicity/economy reasons)
    • when async submission is found (@mode="asynchronous"), store information but do not run submission
    • XFormsServer sends Ajax response and closes connection
    • THEN process queued async submissions
  • Callable instances are added to XFCD when asynchronous submissions are encountered
  • openConnection() was refactored to separate headers processing and remove dependency on ExternalContext
  • XFCD.processAsynchronousSubmissions() is run:
    • at the end of XFormsServer processing
    • at the end of XFormsToXHTML processing
  • converters were refactored so that endDocument() causes the the Servlet OutputStream to be closed
    • allows client to entirely receive Ajax response before async submissions are processed on the server
    • this works in xforms-server.xpl, where oxf:xml-converter/oxf:html-converter are placed before oxf:http-serializer
    • this may not work properly for XFormsToXHTML given the complexity of the epilogue
      • -> async submissions during page initialization may delay the page loading

Background submissions