XForms - Advanced Submissions

Disabling validation and relevance checks

Orbeon Forms supports the XForms 1.1 validate and relevant attributes on <xforms:submission>. These boolean attributes disable processing of validation and relevance respectively for a given submission:

<xforms:submission id="my-submission"
  method="post"
  validate="false"
  relevant="false"
  resource="http://example.org/rest/draft/" replace="none"/>

For more information, please visit the XForms 1.1 specification.

Controlling serialization

Orbeon Forms supports the XForms 1.1 serialization on <xforms:submission>. This is particularly useful to specify the value none with a get method:

<xforms:submission id="my-submission"
  method="get"
  serialization="none"
  resource="http://example.org/document.xml" replace="instance"
  instance="my-instance"/>

For more information, please visit the XForms 1.1 specification.

Read-only XForms instances with xxforms:readonly

Orbeon Forms supports an extension attribute, xxforms:readonly, on the <xforms:instance> and <xforms:submission> elements. When set to true, this attribute signals that once loaded, the instance is read-only, with the following consequences:

  • The instance is loaded into a smaller, more efficient, read-only data structure in memory.
  • Instance values cannot be updated, no Model Item Properties (MIPs) can be assigned with <xforms:bind> to the instance, and the read-only MIP is set to true for all the nodes in the instance. But a read-only instance can be replaced entirely by an <xforms:submission replace="instance">.
  • When using client-side state handling, less data might be transmitted between server and client.

Read-only instances are particularly appropriate for loading internationalization resources, which can be large but don't change.

Example:

<xforms:instance
  id="resources-instance"
  src="/forms/resources/en"
  xxforms:readonly="true"/>

The xxforms:readonly attribute on <xforms:instance> determines if the instance is read-only until that instance is being replaced.

After an instance is replaced, it can be read-only or not irrelevant of the of xxforms:readonly on <xforms:instance>. When the instance is replaced, the replaced instance is read-only if and only if the <xforms:submission> that does the replacement has a attribute xxforms:readonly="true".

When this attribute is set to true on <xforms:submission> and if the targetref attribute is specifed, the replacement target must be an instance's root element.

Caching of XForms instances with xxforms:cache

Availability

This is an Orbeon Forms PE feature.

Configuration

Orbeon Forms supports a boolean extension attribute, xxforms:cache, on the <xforms:instance> and <xforms:submission> elements. This attribute can be used with instances that are read-only or read-write. When set to true:

  • The instance can be shared at the application level. It is identified by its source URL and, in the case of a submission with POST or PUT method, by the body of the request sent.
  • The instance is not stored into the XForms document's state, but in a global cache, therefore potentially saving memory. If, upon loading an XForms instance or running a submission, the instance is found in the cache, it is directly retrieved from the cache. This can save time especially if the URL can take significant time to load.
  • The instance stored in cache is read-only. If the xxforms:readonly attribute is set to true (on <xforms:instance> or <xforms:submission>), a single copy of the instance is used in memory. Otherwise, a read-write copy is made.
  • In general, the URL should refer to a constant or rarely-changing XML document, and authorization credentials such as username and password should not cause different data to be loaded.

NOTE: This attribute deprecates the xxforms:shared attribute. Using xxforms:cache="true" is equivalent to using xxforms:shared="application". Using xxforms:cache="false" is equivalent to using xxforms:shared="document".

Here is how you use the attribute on <xforms:instance>:

<xforms:instance
  id="resources-instance"
  src="/forms/resources/en"
  xxforms:readonly="true"
  xxforms:cache="true"/>

When used on <xforms:submission>, the submission has to use method="get"method="post" or method="put" method and replace="instance":

<xforms:submission
  serialization="none"
  resource="/forms/resources/fr"
  method="get"
  replace="instance"
  instance="resources-instance"
  xxforms:readonly="true"
  xxforms:cache="true"/>

NOTE: Since POST and PUT are not meant to be idempotent methods, you should use xxforms:cache="true" with these methods carefully, typically for calls to services you know are idempotent. Otherwise, incorrect or stale data might be returned by the submission.

You set the size of the shared instances cache using a property in properties.xml:

<property as="xs:integer" name="oxf.xforms.cache.shared-instances.size" value="50"/>

You can force the XForms engine to remove a shared instance from the cache by dispatching the xxforms-instance-invalidate event to it. The next time an XForms document requires this instance, it will not be found in the cache and therefore reloaded. Example:

<xforms:action ev:event="DOMActivate">
    <xforms:send submission="save-submission"/>
    <xforms:dispatch name="xxforms-instance-invalidate" target="data-to-save-instance"/>
</xforms:action>

The xxforms:invalidate-instance action allows invalidating a shared instance by resource URI, for example:

<xxforms:invalidate-instance ev:event="DOMActivate" resource="/forms/resources/fr"/>

This action also supports the xinclude attribute, which if present will only invalidate the instance with the given resource if it was loaded with a matching xxforms:xinclude attribute:

<!-- Submission loading a shared instance and enabling XInclude processing -->
<xforms:submission serialization="none" resource="/forms/resources/fr" method="get"
                   replace="instance" instance="resources-instance"
                   xxforms:readonly="true" xxforms:cache="true" xxforms:xinclude="true"/>
<!-- Action invalidating only the instance which was loaded with xxforms:xinclude="true" -->
<xxforms:invalidate-instance ev:event="DOMActivate" resource="/forms/resources/fr" xinclude="true"/>

If the xinclude attribute is not specified, any shared instance matching the resource URI is invalidated.

It is also possible to remove all shared instances from the cache by using the xxforms:invalidate-instances action, for example:

<xxforms:invalidate-instances ev:event="DOMActivate"/>

The xxforms:ttl attribute can be used to set a time to live for the instance in cache. This duration is expressed in milliseconds and has to be greater than zero. When a shared instance if found in cache but has an associated time to live, if it was put in the cache more than time to live milliseconds in the past, then the instance is discarded from the cache and retrieved again by URI as if it had not been found in cache at all. The following example expires the shared instance after one hour:

<xforms:instance
  id="resources-instance"
  src="/forms/resources/en"
  xxforms:readonly="true"
  xxforms:cache="true"
  
xxforms:ttl="3600000"/>
SECURITY NOTE: When using xxforms:cache="true", be sure that the data contained in the instance does not contain information that could be inadvertently shared with other XForms documents. It is recommended to use it to load localized resources or similar types of data.

HTTP authentication

Username, password and domain

The <xforms:submission> and <xforms:instance> elements support optional attributes to specify HTTP authentication credentials:

  • xxforms:username: HTTP authentication username
  • xxforms:password: HTTP authentication password
  • xxforms:domain: domain for NTLM authentication

If xxforms:username is missing or empty, the other authentication attributes are ignored.

If you specify the xxforms:username without the xxforms:password, the password defaults to an empty string.

<xforms:submission
    id="save-submission"
    ref="instance('my-instance')"
    method="put"
    resource="/exist/rest/ops/my-file.xml"
    replace="none"
    xxforms:username="admin"
    xxforms:password=""/>

NOTE: On  <xforms:instance>, the attributes are statically-defined. On <xforms:submission>, they are AVTs and can therefore be dynamic.

Preemptive authentication

By default, the username and password are provided preemptively to the connection. In this mode, the HTTP client "will send the basic authentication response even before the server gives an unauthorized response in certain situations, thus reducing the overhead of making the connection" (HttpClient documentation).

[SINCE: 2012-04-21]

The xxforms:preemptive-authentication attribute on  <xforms:submission> and <xforms:instance> elements allows controlling this feature. You can disable this feature by setting the property to false:

<xforms:submission xxforms:preemptive-authentication="false" ...>

NOTE: On  <xforms:instance>, the attribute is statically-defined. On <xforms:submission>, it is an AVT and can therefore be dynamic.

HTTP headers forwarding

HTTP requests initiated by <xforms:submission> and <xforms:instance> can automatically forward incoming HTTP headers. Two properties are looked at in order:

  1. The local, XForms-specific oxf.xforms.forward-submission-headers property
  2. The global Orbeon Forms oxf.http.forward-headers property (used only as a default if the XForms property is not set)

Both properties contain a space-separated list of header names to forward:

<property
  as="xs:string"
  name="oxf.xforms.forward-submission-headers"
  value="Orbeon-Client Authorization SM_USER"/>

oxf.xforms.forward-submission-headers can also be set on a per-page basis on your first model element:

<xforms:model
  xxforms:forward-submission-headers="Orbeon-Client Authorization SM_USER">
    ...
</xforms:model>

Whenever an HTTP request must be performed, the XForms engine looks at this list of header names and it forwards the header value if the following conditions are met:

  • There is an incoming header with that name, i.e. either the HTTP request causing the XForms page to load or the XForms Ajax request to run contains that header.
  • There is no author-specifed header with the same name in an <xforms:header> element within <xforms:submission>.

Forwarding the Authorization or other authentication-related headers can be useful to propagate authentication credentials to other services.

NOTE: The Authorization header is treated specially: if a username is specified on the submission with xxforms:username, then this header is never forward.

SECURITY NOTE: Forwarding authentication-related headers may cause a security risks when communicated with non-trusted servers. Use carefully!

Loading indicator

When an <xforms:submission> with replace="all" is executed, in general, the browser will load another page. While this happens, the loading indicator, by default shown in red at the top right of the window, is displayed. However, when the browser is served not a web page but say a ZIP file, the browser might ask you in you want to download it, and then stay in the current page. When this happens, the loading indicator does not go away.

In those cases where you know that the target page does not replace the current page, you can prevent the loading indicator from being displayed by adding the xxforms:show-progress="false"attribute:

<xforms:submission xxforms:show-progress="false"/>

Similarly the xxforms:show-progress="false" attribute can be used with the xforms:load action:

<xforms:load xxforms:show-progress="false"/>

Specifying an HTML target window or frame with the xxforms:target attribute

You can use the xxforms:target attribute on both <xforms:submission> and xforms:load. It behaves just like the HTML target attribute. When used on <xforms:submission>, it only makes sense to use this attribute when you have replace="all". Using this attribute to load a page in a new page is a case where you should add the xxforms:show-progress="false" attribute.

Replacing other instances with the xxforms:instance attribute

On an <xforms:submission> element with replace="instance", the optional instance attribute specifies a destination instance for the result. That attribute is processed like the instance()function, which means that the instance specified must be in the current model.

The xxforms:instance extension attribute can be use instead of the standard instance attribute. It works like instance, except that the instance is searched globally among all models.xxforms:instance is to the instance attribute what the xxforms:instance() function is to the standard instance() function.

<xforms:submission id="my-submission" method="post" resource="http://example.org/"
                   replace="instance" xxforms:instance="my-instance"/>

Enabling XInclude processing with the xxforms:xinclude attribute

On an <xforms:submission> element with replace="instance", the optional xxforms:xinclude attribute specifies whether XInclude processing should be performed on the XML document returned, before storing it into the destination instance. The default is false.

<xforms:submission id="my-submission" method="post" resource="http://example.org/"
                   replace="instance" xxforms:xinclude="true"/>

Preventing recalculation before a submission

[SINCE: 2010-06-16]

XForms 1.1 provides two attributes to control pre-submission tasks:
  • validate: "indicates whether or not the data validation checks of the submission are performed".
  • relevant: "indicates whether or not the relevance pruning of the submission is performed"
Orbeon Forms adds the following attribute:
  • xxforms:calculate: indicates whether or not recalculation must take place
The default value is "false" if the value of serialization is "none" and "true" otherwise.

The purpose of the attribute is to improve performance when multiple submission are called serially. The form author can this way completely prevent the rebuildrecalculate and revalidate flags from being checked before submitting data:

<xforms:submission ref="instance()" method="post"
    validate="false" relevant="false" xxforms:calculate="false" .../>

WARNING: This attribute must be used with caution, as using it might mean you submit information that is out of date.

Here is how Orbeon Forms performs the rebuild, recalculate and revalidate operations before a submission:
  • Perform rebuild if:
    • the deferred flag for rebuild is set
    • and the data to submit belongs to an instance (as opposed to a non-instance XML node)
    • and either of the effective value of the validaterelevant or xxforms:calculate attributes is true
  • Perform recalculate if:
    • the deferred flag for recalculate is set
    • and the data to submit belongs to an instance (as opposed to a non-instance XML node)
    • and either of the effective value of the relevant or xxforms:calculate attributes is true
  • Perform revalidate if:
    • the deferred flag for revalidate is set
    • and the data to submit belongs to an instance (as opposed to a non-instance XML node)
    • and the final effective of the validate attribute is true
The "effective value" for the validaterelevant and xxforms:calculate attributes is the value after considering:
  • each attribute's default value
  • resolution of AVTs

Submitting non-XML content

Submitting text content

Orbeon Forms supports sending the text content of an XML document as per XSLT 2.0 and XQuery 1.0 Serialization. To perform a text submission:

  • The post or put method is required.

  • You must use a the text/plain value for the serialization attribute.

<xforms:instance id="instance">
    <text>
        This contains some text. The<b>string value</b>of the document will be sent
    </text>
</xforms:instance>
...
<xforms:submission id="save-submission" ref="instance()" method="post" serialization="text/plain" replace="none"
                   resource="http://example.com/foo.text"/>
...

Submitting HTML or XHTML content

Orbeon Forms supports sending an XML document as HTML or XHTML as per XSLT 2.0 and XQuery 1.0 Serialization. To perform a HTML or XHTML submission:

  • The post or put method is required.

  • You must use a the text/html or the application/xhtml+xml value for the serialization attribute.

<xforms:instance id="instance">
    <html>
        <head>
            <title>My page</title>
        </head>
        <body>
            <p>Cool HTML!</p>
        </body>
    </html>
</xforms:instance>
...
<xforms:submission id="save-submission" ref="instance()" method="post" serialization="text/html" replace="none"
                   resource="http://example.com/foo.html"/>
...

Submitting binary content

XForms 1.1 does not explicitly support submitting binary content, but does not prohibit it either. Orbeon Forms supports sending the content of a binary resource specified by a URI. Such resources are easily obtained with <xforms:upload>, for example. To perform a binary submission:

  • The post or put method is required.
  • You must use application/octet-stream as serialization attribute.
  • The node referred to by the submission must be of type xs:anyURI.
  • [SINCE 2012-05-30] Relative URLs are supported and resolved as service URLs against the <xforms:submission> element.
<xforms:instance id="attachment">
    <attachment>
        file:/Users/jdoe/Applications/apache-tomcat-5.5.20/temp/xforms_upload_30877.tmp
    </attachment>
</xforms:instance>
<xforms:bind nodeset="instance('attachment')" type="xs:anyURI"/>
...
<xforms:submission id="save-submission" ref="instance('attachment')" method="put" serialization="application/octet-stream"
                   replace="none" resource="http://example.com/foo.bin"/>
...

Alternatively, you can set the type information using the xsi:type attribute:

<xforms:instance id="attachment">
    <attachment xsi:type="xs:anyURI">
        file:/Users/jdoe/Applications/apache-tomcat-5.5.20/temp/xforms_upload_30877.tmp
    </attachment>
</xforms:instance>

Local submissions

Rationale

XForms pages can make heavy use of services through the use of <xforms:submission>. A service is primarily identified by a URL.

  • Sometimes a service is remote (on a machine other than the machine on which Orbeon Forms is installed), in which case the URL is necessarily an absolute URL starting with http:// or https://.

  • But often services are implemented within Orbeon Forms itself, not only on the same server but within the same web application. In the case of such local submission, Orbeon Forms provides a special optimized mode which has the following benefits:

    • No actual HTTP connection is initiated, so performance is likely to be better.

    • There is no need to deal with absolute URLs such as http://localhost:8080, especially when proxies or firewalls are in place.

For more information, see also the configuration properties related to submissions.

Enabling local submissions

Orbeon Forms performs a local submission if:

  • The URL specified is not a absolute, i.e. does not start with http:// or https://.

  • The submission is not asynchronous. (This restriction may be lifted in the future.)

  • In a servlet environment:

    • The submission has replace="all" (which is the default if no replace attribute is specified) and the oxf.xforms.local-submission-forward property is set to true (which is the default).

    • The submission has replace="instance", replace="text" or replace="none" and the oxf.xforms.local-submission-include property is set to true (the default is false).

  • In a portlet environment:

    • The f:url-norewrite attribute is not set to true.

    • The f:url-type attribute is not set to resource.

    NOTE: The portlet logic above is likely to be revised in the future. Also note that in the case of optimized submissions within portlets, requests are made directly to the Orbeon Forms portlet and do not use servlet forward/include.

Context resolution

In a servlet environment, paths are resolved as follows:

  • If f:url-norewrite is not set to true, the resource is resolved against the current servlet context.

  • If f:url-norewrite is set to true, the resource is resolved against the servlet container root. This allows accessing other web applications within the same servlet container.

Say your application is under context /orbeon, and you have a second web application under context /foo:

<!-- This submission calls /orbeon/bar -->
<xforms:submission replace="all" method="post" resource="/bar"/>
<!-- This submission calls /foo/bar -->
<xforms:submission replace="all" method="post" resource="/foo/bar" f:url-norewrite="true"/>

Limitations of includes

With:

  • replace="instance"
  • replace="text"
  • replace="none"

optimized submission are implemented using the servlet container's include mechanism, which does not automatically build path information for the included resource.

In this case, Orbeon Forms is therefore unable to provide proper "servlet path" and "path info" information. Orbeon Forms handles this situation in the following way:

  • A blank ("") "servlet path" is provided.

  • The "path info" contains the entire path provided, instead of the path following the servlet path.

This may cause some application which rely on the "servlet path" information to behave incorrectly. For example, consider the eXist REST servlet:

  • It is mounted as /exist/rest within Orbeon Forms.

  • eXist (quite properly) expects any path following /exist/rest to be a path into the database, e.g. /exist/rest/db/orbeon produces a path called /db/orbeon.

  • If Orbeon Forms calls the eXist REST servlet with a blank servlet path and a path info containing /exist/rest/db/orbeon, eXist obviously obtains an incorrect database path.

NOTE: In short you must be careful when using local includes. The good news is that if you are using servlets which do not depend on path information as explained above, or if you have control over the implementation of the services you are calling, then you can most likely work around this limitation.

Local forwards are not subject to that limitation.

The "echo:" URL scheme

[SINCE: 2011-03-29]

Submissions support a special "echo:" URL scheme which returns the data that was submitted. This is useful for tests.

NOTE: Previously, the undocumented "test:" scheme had the same effect. It is still supported for backward compatibility.

Example:

<xf:submission
  id="my-submission"
  ref="instance()"
  method="post" action="echo:" replace="instance" instance="result"/>


Comments