Comments? Feedback?

This wiki does not yet support public comments (a limitation of Google Sites), so we encourage you to post your comments either:

On Twitter by responding to @orbeon.

On our community mailing list: subscribe sending an email to ops-users-subscribe@ow2.org (content of subject/body doesn't matter), you'll get a response with the email to use to send your message to the community mailing list.

Recent site activity

XForms - JavaScript and CSS Resources

Minimal resources

Most JavaScript and CSS files used by the XForms engine are available in two versions:

  • A full version, which may contain comments, spaces, longer identifiers, etc.
  • A minimal version, which is usually much smaller

Both versions work exactly the same. For development and debugging of the XForms engine itself, the full version is easier to work with. But if you never work directly with these JavaScript and CSS files, as well as for deployment, the minimal versions are recommended as they will load faster in the user's web browser.

You enable minimal resources in properties-local.xml as follows:

<property
  as="xs:boolean"
  name="oxf.xforms.minimal-resources"
  value="true"/>

Default [SINCE 2012-05-03]:
  • prod mode: true
  • dev mode: false
NOTE: Before 2012-05-03, the default was true.

Combined resources

Rationale

Serving external CSS and JavaScript resources can have a high performance cost on page loads. This is particularly important with the intensive use of JavaScript in Orbeon Forms. In particular, it can be shown that serving many small files is slower than serving a single large file.

NOTE: In theory, HTTP pipelining can improve very much on this, but this is (very unfortunately) useless in practice at the time of writing because Internet Explorer doesn't implement it at all and Firefox / Mozilla do implement it but do not enable it by default.

This is why Orbeon Forms supports the option of combining the multiple JavaScript and CSS files required for a given XForms page into one or two JavaScript files and one or two CSS file.

How it works

There are 3 categories of resources:

  • built-in XForms engine resources, like xforms.js
  • XBL components resources, like button.js
  • user resources (placed in the <head> element

Resources are split into 2 groups:

  • baseline resources, which include
    • main built-in XForms engine resources
    • XBL resources for components specified with the oxf.xforms.resources.baseline property
  • other resources, which include
    • other built-in XForms engine resources, such as for the rich text editor or tree selection
    • XBL resources not part of the baseline
    • user resources
The idea is that this way, in an application with multiple pages:
  • a large baseline of resources is loaded and cached once and for all
  • a smaller incremental set of extra resources is loaded for each individual page

If all the resources belong to the baseline, only one JavaScript and one CSS files are produced. Otherwise, two JavaScript and two CSS files are produced.

The URLs produced identify the resources needed by the page, for example:

<link rel="stylesheet"
  href="/orbeon/xforms-server/orbeon-8b3d174e93f2d74146c9b2a5356bd5b8b5e196f8.css"
  type="text/css" media="all">

<link rel="stylesheet"
  href="/orbeon/xforms-server/orbeon-e01218f47e6ecd43fb1c2295ccae2e688c443b62.css"
  type="text/css" media="all">

<script type="text/javascript"
  src="/orbeon/xforms-server/orbeon-19e8d10829ccdd0d9aec779c0c89e5d1f57764dd.js">

<script type="text/javascript"
  src="/orbeon/xforms-server/orbeon-3a3469eca94e6df9783e742067f464b57de4e2f3.js"/>

When the Orbeon Forms XForms server receives a request for a combined resource, it determine what files need to be combined and outputs them all together. Furthmore, for CSS files, all URLs referred to with url() are rewritten, so that links to images, in particular, remain correct.

Some CSS and JavaScript files are never included into aggregated resources:

  • resources with f:url-norewrite="true":
    <xh:link rel="stylesheet" href="/style.css" f:url-norewrite="true"/>
  • resources with an absolute URL, such as:
    <xh:link rel="stylesheet" href="http://example.org/style.css"/>
  • CSS resources with a media attribute that is present but different from "all":
    <xh:link rel="stylesheet" href="/style.css" media="print"/>

Configuration

You enable this feature in properties-local.xml as follows:

<property
  as="xs:boolean"
  name="oxf.xforms.combine-resources"
  value="true"/>

When this is enabled, Orbeon Forms combines JS and CSS resources.

Default [SINCE 2012-05-03]:
  • prod mode: true
  • dev mode: false
NOTE: Before 2012-05-03, the default was true.

Mappings between resources URLs and the resources are stored in the xforms.resources cache, configured in RESOURCES/config/ehcache.xml.

The baseline of resources is configured as follows:

<property
  as="xs:string"
  name="oxf.xforms.resources.baseline"
  value="fr:button fr:tabview fr:autocomplete"/>

The value consists of a list of qualified names referring to XBL components. Resources for the components specified are always included in every page, whether the component is used by the page or not.

In addition, you can enable caching on disk of combined resources with:

<property
  as="xs:boolean"
  name="oxf.xforms.cache-combined-resources"
  value="true"/>

This cache works differently from other Orbeon Forms caches, as the result is stored in the resources, typically under:

WEB-INF/resources/xforms-server/

One benefit of this mechanism is that it allows making such combined files to be served by an Apache front-end.

JavaScript at the bottom of the page

This feature is enabled by default.

[SINCE: 2011-02-21: this used to be built into theme stylesheets. It is now enabled with a property.]

The following property, if enabled, places external and inline JavaScript at the bottom of the page:

<property as="xs:boolean" name="oxf.xforms.resources.javascript-at-bottom" value="true"/>

Versioned resources

Availability

This is an Orbeon Forms PE feature.

This feature is enabled by default in Orbeon Forms PE. [SINCE: 2011-02-21]

Rationale

To further improve caching efficiency, Orbeon Forms supports enabling versioned resources. Usually, a resource such as a CSS, JavaScript or image file, is served through URLs like this one:

http://localhost:8080/orbeon/xforms-server/orbeon-a8adf9b6d7d9e9ed23060a279fabed50bd829236.js

When configuring caching on the server, for example by using an Apache front-end, you may face a dilemma:

  • Caching aggressively (with an expiration date far in the future and no revalidation) so that the client asks for the resource as rarely as possible. Doing so may cause resources on the client to be out of date.

  • Caching for a shorter period of time or by forcing revalidation so that your client always has a fresh version of the resources. Doing so may cause longer page loads and more load on the server.

Orbeon Forms solves this by providing the option of using versioned resources, that is inserting automatically a version number within resource URLs.

Configuration

You enable versioned resources in properties-local.xml:

<property as="xs:boolean" name="oxf.resources.versioned" value="true"/>

With this, the resource above is served as follows:

http://localhost:8080/orbeon/xforms-server/3.6.0.200803010236/orbeon-a8adf9b6d7d9e9ed23060a279fabed50bd829236.js

The XForms Server component, which serves the resource in this case, sets an expiration date far in the future. For example, this is the description of the cache entry in the Firefox about:cache page:

          Key: http://localhost:8080/orbeon/xforms-server/3.6.0.200803010236/orbeon-6535536d5b557b4339c5ebc5b4fc091242fe5546.css
Data size: 22524 bytes
Fetch count: 2
Last modified: 2008-03-01 17:04:25
Expires: 2011-12-25 17:10:42

This means that the resource can effectively be cached "for ever" by a client. In case the client visits Orbeon Forms pages often, the resources will be availabe from cache, therefore reducing page loading times and server load as well.

When Orbeon Forms is upgraded on the server, the version number changes as well. An XForms page will refer to resources with the new version number, so the cached resource is not used by the browser and a new resource is loaded from the server, before being cached. This "magic" is enabled simply with the inclusion of the Orbeon Forms version number in the URL.

Only CSS and JavaScript resources used by the XForms engine are loaded through the XForms Server component. Other resources like images referred by XForms stylesheets are served by the Page Flow Controller, through URLs like this one:

http://localhost:8080/orbeon/ops/images/xforms/error.gif

With resource versioning enabled, the URL becomes:

http://localhost:8080/orbeon/3.6.0.200803010236/ops/images/xforms/error.gif

When resource versioning is enabled, the Page Flow Controller by default serves all the resources defined in <files> elements by first checking the oxf.resources.versioned property. If versioning is enabled, the PFC removes the version number from the URL before searching for the resource on disk. It is possible to turn this behavior on and off selectively with the versioned attribute. Here is how to turn off versioning for PDF files in page-flow.xml:

<config xmlns="http://www.orbeon.com/oxf/controller" xmlns:oxf="http://www.orbeon.com/oxf/processors"><!-- GIF images are loaded following oxf.resources.versioned --><files path-info="*.gif"/><!-- More file definitions here -->...<!-- PDF files are not versioned --><files path-info="*.pdf" versioned="false"/><!-- More file definitions here -->...<!-- More page definitions here -->...</config>

Conversely, resource URLs produced by an XForms page are automatically rewritten following the Page Flow's <files> definitions.

The versioning mechanism is made available to your own application resources as well. Any resource whose path doesn't start with /ops/ or /config/ is considered part of your application, not of Orbeon Forms. In that case, the Orbeon Forms version number is not used, but you specify instead an application version number in properties-local.xml:

<property as="xs:string" name="oxf.resources.version-number" value="1.6.3"/>

Note that if this property is commented out or missing, no versioning takes place for your application resources even if oxf.resources.versioned is set to true.

For deployed application, you should upgrade the application version number whenever you modify application resources so that clients retrieve the proper resources.

The following scenario shows the entire lifecycle for application resources:

  • You an image as RESOURCES/apps/foo/bar.png

  • You refer to it as:

    <xhtml:body><xhtml:img src="/apps/foo/bar.png" alt="My Image"/></xhtml:body>
  • With versioning enabled, the image path is rewritten automatically as follows:

    /1.6.3/apps/foo/bar.png

    Note that the application resource number is used because the resource is not part of Orbeon Forms.

  • Your browser sees a URL like:

    http://localhost:8080/orbeon/1.6.3/apps/foo/bar.png
  • When the browser loads the image, the PFC receives back:

    /1.6.3/apps/foo/bar.png
  • The PFC knows that PNG files are versioned, so removes the version number and sends this resource to the browser:

    RESOURCES/apps/foo/bar.png

From client-side JavaScript, you can access the application version number as follow:

var version = ORBEON.util.Utils.getProperty(APPLICATION_RESOURCES_VERSION_PROPERTY);

Since 2011-10-05, versioned resources served by the PFC (that is all the resources except the XForms engine's CSS and JavaScript resources) also get an aggressive expiration date.

Before 2011-10-05, versioned resources served by the PFC would get the usual HTTP "age of the resource plus 10%" expiration heuristic instead of an aggressive expiration date. If you want to fully leverage client-side caching capabilities, you may want to use an Apache front-end or a Servlet filter to modify the Expires header of those resources. With Apache, you can use mod_expires.

In case you use Apache, you can in addition configure a rewriting rule with mod_rewrite to allow Apache to directly load resources containing a version number, as shown below.

Note

We recommend restarting Orbeon Forms after changing the oxf.resources.versioned property, as data in Orbeon Forms caches may not be made aware of the change until the next restart.

Examples of Apache configurations

Here is how you can configure Apache to serve Orbeon Forms resources. This assumes the following:

  • Orbeon Forms deployed under the /orbeon context
  • Orbeon Forms exploded WAR file under /home/orbeon/war/
  • orbeon-resources-public.jar unziped under /home/orbeon/war/WEB-INF/orbeon-resources-public/
  • oxf.xforms.cache-combined-resources set to true in properties-local.xml

Without resources versioning:

RewriteEngine on
# Rewrite CSS and JavaScript resources served by the XForms Server
# -> make sure "oxf.xforms.cache-combined-resources" is set to "true" in properties-local.xml
RewriteRule ^/orbeon/(xforms-server/.*\.(css|js))$ /home/orbeon/war/WEB-INF/resources/$1 [L]
# Serve /config/theme resources
# -> make sure orbeon-resources-public.jar is unzipped under "orbeon-resources-public"
RewriteRule ^/orbeon/(config/theme/.*\.(css|png|gif))$ /home/orbeon/war/WEB-INF/orbeon-resources-public/$1 [L]
# Special handling of PNG images for IE 6
RewriteCond %{HTTP_USER_AGENT} .*MSIE\ 6.*
# Make sure the corresponding GIF image exists
RewriteCond /home/orbeon/war/WEB-INF/orbeon-resources-public/$1.gif -f
# Match on PNG images only and rewrite to GIF
RewriteRule ^/orbeon/((ops|config/theme|xbl/orbeon)/.*)\.png$ /home/orbeon/war/WEB-INF/orbeon-resources-public/$1.gif [L]
# Serve /ops resources
# -> make sure orbeon-resources-public.jar is unzipped under "orbeon-resources-public"
RewriteRule ^/orbeon/((ops|config/theme|xbl/orbeon)/.*\.(gif|css|pdf|json|js|png|jpg|xsd|htc|ico|swf))$ /home/orbeon/war/WEB-INF/orbeon-resources-public/$1 [L]
# Special handling of PNG images for IE 6
RewriteCond %{HTTP_USER_AGENT} .*MSIE\ 6.*
# Make sure the corresponding GIF image exists
RewriteCond /home/orbeon/war/WEB-INF/resources/$1.gif -f
# Match on PNG images only and rewrite to GIF
RewriteRule ^/orbeon/(.*)\.png$ /home/orbeon/war/WEB-INF/resources/$1.gif [L]
# Serve remaining resources
RewriteRule ^/orbeon/(.*\.(gif|css|pdf|json|js|png|jpg|xsd|htc|ico|swf))$ /home/orbeon/war/WEB-INF/resources/$1 [L]

With resources versioning:

RewriteEngine on
# Rewrite CSS and JavaScript resources served by the XForms Server
# -> make sure "oxf.xforms.cache-combined-resources" is set to "true" in properties-local.xml
RewriteRule ^/orbeon/xforms-server/[^/]+/(.*\.(css|js))$ /home/orbeon/war/WEB-INF/resources/xforms-server/$1 [L]
# Set far expiration date
<LocationMatch "^/orbeon/xforms-server/([^/]+/.*\.(css|js))$">
Header set Expires "Wed, 1 Jan 2020 12:00:00 GMT"
</LocationMatch>

# Special handling of PNG images for IE 6
RewriteCond %{HTTP_USER_AGENT} .*MSIE\ 6.*
# Make sure the corresponding GIF image exists
RewriteCond /home/orbeon/war/WEB-INF/orbeon-resources-public/$1.gif -f
# Match on PNG images only and rewrite to GIF
RewriteRule ^/orbeon/[^/]+/((ops|config/theme|xbl/orbeon)/.*)\.png$ /home/orbeon/war/WEB-INF/orbeon-resources-public/$1.gif [L]
# Serve /ops resources
# -> make sure orbeon-resources-public.jar is unzipped under "orbeon-resources-public"
RewriteRule ^/orbeon/[^/]+/((ops|config/theme|xbl/orbeon)/.*\.(gif|css|pdf|json|js|png|jpg|xsd|htc|ico|swf))$ /home/orbeon/war/WEB-INF/orbeon-resources-public/$1 [L]
# Set far expiration date
<LocationMatch "^/orbeon/[^/]+/((ops|config/theme|xbl/orbeon)/.*\.(gif|css|pdf|json|js|png|jpg|xsd|htc|ico|swf))$">
Header set Expires "Wed, 1 Jan 2020 12:00:00 GMT"
</LocationMatch>

# Special handling of PNG images for IE 6
RewriteCond %{HTTP_USER_AGENT} .*MSIE\ 6.*
# Make sure the corresponding GIF image exists
RewriteCond /home/orbeon/war/WEB-INF/resources/$1.gif -f
# Match on PNG images only and rewrite to GIF
RewriteRule ^/orbeon/[^/]+/(.*)\.png$ /home/orbeon/war/WEB-INF/resources/$1.gif [L]
# Serve remaining resources
RewriteRule ^/orbeon/[^/]+/(.*\.(gif|css|pdf|json|js|png|jpg|xsd|htc|ico|swf))$ /home/orbeon/war/WEB-INF/resources/$1 [L]
# Set far expiration date
<LocationMatch "^/orbeon/[^/]+/(.*\.(gif|css|pdf|json|js|png|jpg|xsd|htc|ico|swf))$">
Header set Expires "Wed, 1 Jan 2020 12:00:00 GMT"
</LocationMatch>
Note

The rewriting rules above have special handling of PNG images for IE 6: when that browser is detected, any request for PNG image having a corresponding GIF image serves the GIF images instead. If you don't need that behavior, remove the corresponding lines in the rules above.

All in all, the rules above perform the following:

  • Special handling for XForms JavaScript and CSS files (using the cached/combined/minimized resources)
  • Serving of /config/theme resources originally in orbeon-resources-public.jar
  • Special handling of PNG images for IE 6 for /ops resources originally in orbeon-resources-public.jar
  • Serving of other /ops resources originally in orbeon-resources-public.jar
  • Special handling of PNG images for IE 6 for resources under RESOURCES
  • Serving of other resources under RESOURCES
  • Marking all versioned resources with an expiration date in the far future