XForms - Offline Mode Internals

This page is obsolete and available for historical purposes only.

Status

Support for the offline was introduced in Orbeon Forms 3.7 and  removed in Orbeon Forms 3.8. See also #1221.

Taking a form offline

There are two ways in which a form can be taken offline:

  • User activates button that has a xxforms-offline class (the server put it there because it noticed that it runs the action <xxforms:offline> when activated). This typically happens when the user clicks on a "Take offline" button on the page.
  • By dispatching the xxforms-offline event on $containing-document$. This typically happens when a form is taken offline from a summary page.

In both cases, the client knows that this is an action to take the form offline and sends the initial dynamic state in addition to the static and dynamic state, as in:

<xxforms:event-request xmlns:xxforms="http://orbeon.org/oxf/xml/xforms">
<xxforms:static-state>pers:6302901B-4452-826C-5300-2027E84CFB3B</xxforms:static-state>
<xxforms:dynamic-state>pers:2C09A273-D2FC-DC67-1A03-854C8FD5C4D7</xxforms:dynamic-state>
<xxforms:initial-dynamic-state>pers:2C09A273-D2FC-DC67-1A03-854C8FD5C4D7</xxforms:initial-dynamic-state>
...
</xxforms:event-request>

In the response, the server switches to client state handling, and sends an <xxforms:offline> action to the client:

<xxf:event-response xmlns:xxf="http://orbeon.org/oxf/xml/xforms">
<xxf:static-state container-type="servlet">X2y6DZ/6qm2DWVzQH7HSj6nzfGyy6n2Ih...</xxf:static-state>
<xxf:dynamic-state>X2y6DZ/6qm2DWRH8APoRCiXE4xKc3UwXBioXBsNoXzVrnvidkMA...</xxf:dynamic-state>
<xxf:action>
<xxf:control-values>
<xxf:control id="xforms-element-24" relevant="false"/>
<xxf:control id="xforms-element-27" relevant="true"/>
</xxf:control-values>
<xxf:offline>
<xxf:events>...</xxf:events>
<xxf:mappings>...</xxf:mappings>
</xxf:offline>
</xxf:action>
</xxf:event-response>

The <xxforms:events> element contains the actions the client will need to run after the initial HTML is loaded from the Gears store to restore the page in its current state. In contains escaped XML, for instance:

<xxf:event-response xmlns:xxf="http://orbeon.org/oxf/xml/xforms">
<xxf:action>
<xxf:control-values>
<xxf:control id="xforms-element-24" relevant="false"/>
<xxf:control id="xforms-element-27" relevant="true"/>
</xxf:control-values>
</xxf:action>
</xxf:event-response>

The <xxforms:mappings> element contains:

  • For each control:
    • All the MIPs, for each MIP:
      • The value of the MIP
      • An array of other controls that inherit this MIP (for relevant and read-only)
  • For each variable:
    • The ID of the control bound to that variable

"mips": {
"xforms-element-14":
{"type": {
"value": "{http://www.w3.org/2001/XMLSchema}integer"
}},
"xforms-element-16":
{"relevant": {
"value": "$a = '42'",
"inherited": ["relevant-inherited-attribute-control","relevant-inherited-element-control"]
}},
"xforms-element-18":
{"constraint": {
"value": ". = $b"
}},
"xforms-element-20":
{"required": {
"value": "$c = '42'"
}},
"xforms-element-22":
{"readonly": {
"value":"$d = '42'"
}},
},
"variables": {
"d": { "value": "xforms-element-20" },
"a": { "value": "xforms-element-14" },
"c": { "value": "xforms-element-18" },
"b": { "value": "xforms-element-16" },
"e": { "value": "xforms-element-22"}
} } }}

About going offline

Some random notes below:

When going offline:
  • It is assumed that the client has an active session with the server.
  • The client sends to the server the id of the “initial dynamic state”, which represents the state of the page right after it was first loaded.
  • The server, upon going offline, computes a list of all the differences between the initial state and the current state of the page.
  • This list is sent to the client and the client stores it into Gers.
  • When the HTML form page is loaded from Gears while offline, the client replays all those events to reproduce the state of the page just before going offline.
  • Then the client updates the page with the values entered by the user while offline, if any.

About going online

When going online, the client sends many events to the server, including, in the end, the xxforms-online event.

If you modify 300 values while offline, then go offline, 300 values are sent to the server, as 300 separate events. Because those values are set into instances, and therefore equivalent to run xforms:setvalue, a refresh of the controls on the server happens after the completion of each event.

This is a desirable situation in general when receiving an Ajax request, because user actions are queued and it makes sense that if the user did a few changes in a row, packed in the same Ajax request, the result would be the same as if the user had done those changes slower.

When going online though, this is costly.

In the general case, we cannot remove the refresh. However, we make the assumption in offline mode that controls statically bound to nodes, that is their bindings do not change over the time the controls are offline. Given this assumption, we can safely remove intermediate refreshes, and instead just ensuring that model rebuild/recalculate take place when needed between events. So this is what is being done:

    * Detect whether there is an xxforms-online event in the Ajax request

    * If so, does intermediate rebuild/recalculate instead of intermediate “everything including refresh”

This significantly improves performance.

Comments