Version 2.5

Historical note: OXF 2.5 was released on July 13, 2004

New in version 2.5.4

Package name in examples and documentation

Some examples and sections of the documentation where still referring to the class org.orbeon.oxf.processor.pipeline.PipelineContext which has been moved in org.orbeon.oxf.pipeline.api.PipelineContext. In particular, this prevented some examples using the Java processor from working properly.

New in version 2.5.3

OXF server renamed to orbeon presentation server

OXF Server is now called Orbeon Presentation Server. The new naming is consistent with the other components of the Open Integration Suite open source project.

Command-line client

  • The command-line client is now simpler and easier to use. The documentation reflects this change.

Pipeline API for java

  • The pipeline API is now exposed and documented. It allows running pipelines from any Java application. Please visit the documentation for more information.

New in version 2.5.2

XForms changes

  • A new reference XForms documentation is included.
  • The schema for XForms controls now allows for text inside an <xforms:repeat> element.
  • Using the <xforms:select> element without an appearance attribute no longer throws an exception.

Bizdoc application improvements

  • The BizDoc example application now works out of the box with WebLogic 8.1 and WebSphere 5.1.
  • The look and feel of the BizDoc example application has been improved and is now consistent between the version integrated with the OXF examples and the standalone version.

New in version 2.5.1

Packaging

This version fixes a minor packaging issue.

New in version 2.5

Compatibility with OXF 2.2

OXF 2.5 features several improvements that may require changes to existing applications running on OXF 2.2. When migrating your existing applications please pay special attention to the following areas:

Major changes

XForms

Primary enhancements to the XForms engine in OXF 2.5 include:

  • Support for the XForms repeat module (repeated portions of the UI)
  • Support for XForms model item properties (validation, calculation, and visibility rules attached to the XForms instance)
  • XML Schema validation
  • Encryption of HTML field names and hidden field values
  • Full control on HTML generation from XForms

Below is a description of each of these enhancements as well as a list of minor changes to the OXF XForms engine.

  • Enhancements:
    • The following elements in the XForms repeat module are now supported: repeat, itemset, insert, and delete. With the XForms repeat module you can easily create pages where XForms controls are repeated. For example you can create an invoice made of line items (description, unit price, quantity) where lines can be added, edited, or deleted.

      The UBL Order example illustrates this scenario. Here is a portion of the UBL example view that shows how <xforms:repeat> is being used. In this example, a line in an HTML table is generated for each order line from the XForms instance. On each line, a "remove" button is inserted. Note the <xforms:delete> action in the <xforms:sbumit>. When the button is pressed, the action will be executed and the corresponding line will be removed. The index() function returns the current index in the iterated nodeset. The first argument of index() is a nodeset id, declared with the id attribute on the <xforms:repeat> element (in this case, the id is: lineSet).

      <xforms:repeat nodeset="order:Order/cat:OrderLine" id="lineSet">
      <xhtml:tr>
      <xhtml:td>
      <xforms:input ref="cat:Item/cat:Description"/>
      </xhtml:td>
      <xhtml:td align="center">
      <xforms:submit xxforms:appearance="image">
      <xxforms:img src="/images/remove.png"/>
      <xforms:label/>
      <xforms:delete nodeset="/form/order:Order/cat:OrderLine" at="index('lineSet')"/>
      </xforms:submit>
      </xhtml:td>
      </xhtml:tr>
      </xforms:repeat>

      The Repeating Elements example illustrates a case of nested repeat.

    • Rules can be attached to elements and attributes of an XForms instance. These are called "model item properties" in XForms and they are used to:

      • Restrict the set of valid values for of an element or attribute (with XML Schema simple types like xs:positiveInteger, by making a value mandatory, or by providing an XPath expression that validates the value).
      • Indicate that the value of a particular element or attribute is to be calculated by the XForms engine (calculation defined in the XPath language).
      • Limit the access to an XForms control, such as a text field, bound to a specific element or attribute (allowing read-only access to the control, allowing no access to the control).
      You will find a very simple example of <xforms:bind> in the XForms text example. In this example we check that the correct password is entered with an XForms model that contains:
      <xforms:model>
      <xforms:instance>
      <form>
      <secret>42</secret>
      </form>
      </xforms:instance>
      <xforms:bind nodeset="/form/secret" constraint="string(.) = '42'"/>
      </xforms:model>
    • You can make sure that the XForms instance conforms to a given schema by referencing this schema from the XForms model. You accomplish this by using the schema attribute on the <xforms:model> element. For instance:

      <xforms:model schema="employee.xsd">
      <xforms:instance>
      <employee>
      <age>-41</age>
      ...
      </employee>
      </xforms:instance>
      </xforms:model>

      In the example above, let's assume the schema, employee.xsd, indicates that the content of <age> must be a positive integer (xs:positiveInteger). If the end-user enters a negative value then the XForms engine annotates the <age> element in the XForms instance with an attribute xxforms:valid="false". The model can look for this annotation if it depends on the instance being valid.

      Additionally the view can inform the end-user of the error via a control bound to the <age> element. For instance:

      <xforms:input ref="age">
      <xforms:alert>The age must be a positive number</xforms:alert>
      </xforms:input>

      If the end-user enters an invalid value, the alert will be displayed in the generated HTML as shown in the screenshot below. Note that you can fully control how errors are displayed by customizing the provided xforms-to-xhtml.xsl stylesheet.

    • With OXF, part of the state of the application is stored in hidden HTML input fields. You can encrypt values in hidden input fields as well as the names of HTML form elements and by doing so prevent a malicious end-user from discovering or modifying the internal state of your application. You encrypt hidden input field values by setting the oxf.xforms.encrypt-hidden property to true in properties.xml.

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

      You encrypt the names of HTML form elements by setting the oxf.xforms.encrypt-names property to true in properties.xml:

      <property as="xs:boolean" name="oxf.xforms.encrypt-names" value="true"/>
    • Before OXF 2.5, the output of the view was going through the "XForms output prologue" (if one was declared in the controller.xml), the XForms output, and finally the epilogue. The XForms output used to transform XForms controls to XHTML form elements.

      In OXF 2.5, things are done differently to make the whole process simpler and more explicit, and to grant you full control over the generated XHTML. Specifically:

      1. The output of the view goes directly to the epilogue.
      2. The XForms output processor is explicitly called from the epilogue.
      3. There is no need for an "XForms output prologue". If you want to transform the output of the view before it goes to the XForms output processor just add that transformation in the epilogue pipeline.
      4. The XForms output processor does not replace XForms elements with XHTML form elements. Instead, it adds annotation to the XForms elements so they can be easily transformed into XHTML later using a simple stylesheet. In fact OXF comes with a stylesheet, xforms-to-xhtml.xsl, that does just that. You can modify this stylesheet to customize the generated XHTML, or you can replace it altogether with your own stylesheet if you want to generate something else (say SVG) instead of XHTML.

      The figure below provides an overview of the transformation done in the epilogue:

    • Nested groups are now supported. For instance:
      <xforms:group ref="/form">
      <xforms:group ref="address">
      ...
      </xforms:group>
      Is equivalent to:
      <xforms:group ref="/form/address">
      ...
      </xforms:group>
    • Support for <xforms:caption>, which is not part of the final XForms specification, has been replaced with support for <xforms:label>, which is part of the final XForms specification.
    • When multiple values are selected in a list or checkboxes the string containing the space separated list of selected values is stored in the element or attribute bound to the control. Also, see the XForms selection example.
    • You must use the namespace http://www.w3.org/2002/xforms for all of your XForms elements as support for the old XForms namespaces has been removed.
    • Previously the XForms engine evaluated the ref attribute in <xforms:filename> and <xforms:mediatype> in the same context as the ref attribute in the parent element. Now the engine evaluates them in the context defined by the ref attribute in <xforms:upload>, as per the XForms specification.

XHTML support

The standard document format for page templates is now XHTML. With previous versions of OXF, a format particular to OXF was used in the http://orbeon.org/oxf/xml/document namespace. You would typically declare this namespace as follows: xmlns:d="http://orbeon.org/oxf/xml/document". Page templates looked like:

<d:document xmlns:d="http://orbeon.org/oxf/xml/document">
<d:head>
<d:title>Home Page</d:title>
</d:head>
<d:body>
<p>Page content.</p>
</d:body>
</d:document>

The same document should now look as follows:

<xhtml:xhtml xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xhtml:head>
<xhtml:title>Home Page</xhtml:title>
</xhtml:head>
<xhtml:body>
<p>Page content.</p>
</xhtml:body>
</xhtml:xhtml>

While the differences between the XHTML and the OXF "document" format are minor, using XHTML has the following benefits:

  • XHTML is a fully documented W3C standard
  • XHTML looks instantly familiar to any HTML developer

The OXF "document" format or the XHTML format are converted into regular HTML in the epilogue defined in your Page Flow file. The new standard OXF epilogue now only handles XHTML. If you have made changes to your epilogue file that depend on the OXF "document" format, you may have to convert to using the XHTML format instead.

Page Flow Controller

  • For the sake of clarity we have renamed the Web Application Controller the Page Flow Controller. Similarly files that were in the examples and named controller.xml have been renamed page-flow.xml.

  • NOTE: Using the name page-flow.xml is not mandatory, but is the recommended naming practice. If you are migrating from OXF 2.2, it is also recommended to rename your controller.xml files to page-flow.xml. If you do so, please update the reference to controller.xml in your web.xml as well.
  • The <view> element is not supported anymore. Attributes on the <view> element were used to define:

    1. The epilogue
    2. What happens when no page is found
    3. The namespace and prefix used by the XForms engine when generating XHTML elements
    4. An optional pipeline called "XForms output prologue" to be executed on the output of the view before the XForms engine transforms the XForms elements in XHTML

    Let's see how those translate in the new page-flow.xml syntax:

    1. The epilogue is referenced with an <epilogue> element, for instance:
      <epilogue url="/config/epilogue.xpl"/>
    2. Instead of pointing to a pipeline to be executed when no page is found, you now define the id of the page to be displayed in that case, for example:
      <page id="not-found" path-info="/not-found" view="/config/not-found.xml"/>
      <not-found-handler page="not-found"/>
    3. As we have seen above in the XForms section, the XForms engine does not generate XHTML directly but instead decorates the XForms elements, which are then transformed in XHTML in xforms-to-xhtml.xsl, itself is called from the epilogue. So that stylesheet now fully controls the generated elements. The provided xforms-to-xhtml.xsl generates XHTML elements in the XHTML namespace.
    4. The OXF processor part of the OXF XForms engine that decorates the XForms elements is ran from the epilogue. If you need to run a transformation on the output of the view before it goes to the XForms engine, you now insert this transformation by modifying the epilogue.xpl. As a result, an "XForms output prologue" is no longer needed.

    Note that the pre-OXF 2.5 <view> element is not supported anymore. Consequently, you will need to change your page flow when upgrading to OXF 2.5.

  • You can now control what method is used to transitions from one page to the other. Consider this page flow:

    <page id="a" path-info="/a" xforms="..." model="..." view="...">
    <action when="...">
    <result page="b"/>
    </action>
    </page>
    <page id="b" path-info="/b" xforms="..." model="..." view="..."/>

    Going from page "a" to page "b" can be done with either a "forward" or a "redirect":

    Redirect
    Forward

    The "forward" method is new in OXF 2.5. The benefit of the "redirect" method is that after being redirected to page b, the end-user will see a URL starting with /b in the browser's address bar. He/she will also be able to bookmark that page and come back to it later. However, a drawback is that the request for page b is sent by the browser with a GET method. Since browsers impose limits on the maximum amount of information that can be sent in a major GET (URL length), this method might not work if the amount of information that needs to be passed to page b from page a is too large. This typically happens when working with fairly large XForms instances. In those cases, you must use the "forward" method, which does not limit the amount of information passed from page to page. The "forward" method also reduces the number of roundtrips with the server.

    You can configure the method:

    1. At the application level, in properties.xml with:
      <property as="xs:string" processor-name="oxf:page-flow" name="instance-passing" value="forward|redirect"/>
    2. At the page flow level with the instance-passing attribute on the page flow root element:
      <config instance-passing="forward|redirect">...</config>
    3. In the page flow at the "result" level, with the instance-passing attribute on the <result> element:
      <page id="a" path-info="/a" xforms="..." model="..." view="...">
      <action when="...">
      <result page="b" instance-passing="forward|redirect"/>
      </action>
      </page>

    A configuration at the application level (properties.xml) can be overridden by a configuration at the page flow level (instance-passing on the root element), which can in its turn be overridden by a configuration at the result level (instance-passing on the <result> element).

Default XSLT transformer

Saxon 7.9.1 is now the default and recommended XSLT transformer. Saxon rivals Xalan in terms of performance and is better aligned with changes in the XSLT specification. In particular, Saxon supports XSLT 2.0, which offers major improvements over XSLT 1.0.

This means that when you use the oxf:xslt processor the XSLT input is processed by Saxon. If your existing code makes use of Xalan-specific extensions you must do one of the following (in order of preference):

  • Standard XSLT constructs supported by Saxon
  • EXSLT extensions supported by Saxon
  • Saxon-specific extensions
  • Refer explicitly to the Xalan tranformer by using oxf:xalan

The Page Flow Controller uses the default XSLT transformer for processing XSLT page templates referenced directly by the Page Flow. If you have an XSLT page template that must be processed by an alternate XSLT transformer you must use a pipeline that calls your XSLT transformer. For example, if your page definition in the Page Flow is as follows:

<page view="my-view.xsl"/>

Change it to call an XPL pipeline instead:

<page view="my-view.xpl"/>

And embed, or refer to your existing stylesheet from the newly created pipeline:

<p:config>
<p:param type="input" name="data"/>
<p:param type="output" name="data"/>
<p:processor name="oxf:xalan">
<p:input name="config" href="my-view.xsl"/>
<p:input name="data" href="#data"/>
<p:output name="data" ref="data"/>
</p:processor>
</p:config>

Pipelines / XPL

  • Processors are now referenced by name instead of URI. For instance, the URI for the XSLT processor was oxf/processor/xslt and this processor was called in an XPL file with:

    <p:processor uri="oxf/processor/xslt">
    ...
    </p:processor>

    Starting with OXF 2.5, the name of this processor is oxf:xslt, where oxf is a prefix mapped to the namespace http://www.orbeon.com/oxf/processors. You call the XSLT processor in OXF 2.5 with:

    <p:processor name="oxf:xslt">
    ...
    </p:processor>

    All the OXF processors are in the http://www.orbeon.com/oxf/processors namespace. When creating your own processors, choose a namespace (e.g. http://www.acme.com/oxf/processors), and create processor names in that namespace (e.g. acme:my-processor).

    Using URIs to reference processors is deprecated: you can still use URIs in OXF 2.5, however URIs support might be dropped in a future release. Until that happens, you can optionally provide a URI in addition to a name when you declare your own processors in processors.xml. For example, you could have:

    <processor name="acme:my-processor" uri="oxf/processor/my-processor">
    <class name="com.acme.MyProcessor"/>
    </processor>
  • You can now have a <p:for-each> that does not produce a document. You do this by not having any of the root, id, or ref attribute on the <p:for-each> element. This example issues one SQL request (e.g. an insert or an update as we are not interested in the output) for each employee contained in a document:

    <p:for-each href="#employees" select="/employees/employee">
    <p:processor name="oxf:sql">
    <p:input name="data" href="current()"/>
    <p:input name="config">...</p:input>
    <p:output name="data" id="sql-out"/>
    </p:processor>
    <p:processor name="oxf:null-serializer">
    <p:input name="data" href="#sql-out"/>
    </p:processor>
    </p:for-each>
  • When no id that can be reused later is defined in any branch of a <p:choose>, then <p:otherwise> is optional. For instance, say you have want to save in a file an "employee" document if his salary is above $100K, you can write in your pipeline:

    <p:choose href="#employee">
    <p:when test="/employee/salary &gt; 100000">
    <p:processor name="oxf:file-serializer">
    <p:input name="config">
    <config>
    <file>highly-paid-employee.xml</file>
    ...
    </config>
    </p:input>
    <p:input name="data" href="#employee"/>
    </p:processor>
    </p:when>
    </p:choose>
  • You can now reference ids declared outside a <p:for-each> from inside the <p:for-each>.
  • You can now reference the current document with current() in a <p:for-each> from statements inside a <p:choose>, itself in the <p:for-each>.
  • Several issues with <p:for-each> have been fixed. Those were particularly visible when using nested <p:for-each>.

Properties

The format of the OXF properties files, available as config/properties.xml, now supports:

  • a syntax to specify value types based on XML Schema types
  • processor-specific properties

Properties global to OXF have the following syntax:

<property as="xs:integer" name="oxf.cache.size" value="200"/>

The as attribute specifies the type, according to the XML Schema conventions, of the value of the property stored in the value attribute. The name attribute specifies the name of the property. The following types are currently available:

  • xs:string
  • xs:integer
  • xs:boolean
  • xs:date
  • xs:dateTime
  • xs:QName
  • xs:anyURI

Processor-specific properties have an additional processor attribute that specifies the name of the processor it applies to. For example:

<property as="xs:string" processor-name="oxf:page-flow" name="instance-passing" value="redirect"/>

The example above means that the instance-passing property of the oxf:page-flow processor is set to the string value redirect. Only the oxf:page-flow processor "sees" this property.

The xs and oxf prefixes must be defined at the beginning of the properties file. Please refer to the standard properties file under config/properties.xml directory for a complete example.

Note that property types depend on property names. For example, the oxf:page-flow processor expects an instance-passing property of type xs:string. Specifying an other type will cause an error.

Several properties have been renamed:

  • oxf.log4j-config replaces oxf.servlet.log4j
  • All processor-specific properties, ones that had names of the form oxf.processor_name.property_name, now have names of the form oxf.property_name. The scheme described above is used to indicate the processor the property applies to.

JDK 1.4 and supported application servers

OXF 2.5 requires the JDK 1.4. Consequently, application servers that only run with JDK 1.3 are no longer supported. Supported application servers include:

For more information on supported application servers, please send your questions to info@orbeon.com.

Other changes

Scope generator and scope serializer

The Session generator and Session serializer processors are deprecated. They are replaced by the Scope generator and Scope serializer processors, which can store and retrieve documents from the session scope, but also from the application and request scopes.

Session listeners

You can setup a processor to be executed when a session is created and when it is destroyed. Typically, one would use this feature to run a pipeline loading and storing the session scope the user's profile when that user logs in (see the Scope generator and serializer above). This can be set up in the Web application configuration (web.xml) with:

<context-param>
<param-name>oxf.session-created-processor.name</param-name>
<param-value>{http://www.orbeon.com/oxf/processors}pipeline</param-value>
</context-param>
<context-param>
<param-name>oxf.session-created-processor.input.config</param-name>
<param-value>oxf:/context/session-created.xpl</param-value>
</context-param>
<context-param>
<param-name>oxf.session-destroyed-processor.name</param-name>
<param-value>{http://www.orbeon.com/oxf/processors}pipeline</param-value>
</context-param>
<context-param>
<param-name>oxf.session-destroyed-processor.input.config</param-name>
<param-value>oxf:/context/session-destroyed.xpl</param-value>
</context-param>

With the above configuration, the pipeline oxf:/context/session-created.xpl will run when users log in, and oxf:/context/session-destroyed.xpl will run when users log out, or when their session expires.

XUpdate

  • New XUpdate elements:
    • <xu:message> ? Just like the XSLT <xsl:message>, the content of the element is evaluated and logged. This is typically used to debug an XUpdate program.
    • <xu:error> ? The XUpdate program is interrupted as an exception is thrown with the result of the evaluation of the element content.
    • <xu:namespace> ? Adds a namespace declaration on the current element, just like the XSLT <xsl:namespace>.
  • New XPath functions:
    • The XPath 2.0 function get-namespace-uri-for-prefix() is supported (the XPath engine is still 1.0 compliant, not 2.0).
    • evaluate(xpath, namespaces, nodeset) ? Evaluates the first string argument as an XPath expression in the context of the third nodeset argument. Any prefix used in the XPath expression must be defined in the second argument, which is a nodeset of namespace nodes.
  • Bug fixes:
    • In some cases, when multiple statements are used in a <xu:for-each>, a statement could change the context and the subsequent statement would execute with an incorrect context. This issue is now fixed.
    • Recursive functions are now allowed.

Java processor

The Java processor now also includes classes from the WEB-INF/classes directory when compiling Java files stored in the resources directory. This way you can put support classes directly in WEB-INF/classes without having to package them in a JAR and to deploy this JAR in WEB-INF/lib.

XInclude support

You can now use XInclude in any XML file. For example, you can have an XForms instance declared in a file and the XForms model in another file, with the later including the former with XInclude. Say you have a document that defines the structure of an employee in employee.xml:

<employee>
<firstname/>
<lastname/>
<salary/>
...
</employee>

Your XForms model can then include this document as an XForms instance with an XInclude element. That element must be in the http://www.w3.org/2001/XInclude namespace:

<xforms:model>
<xforms:instance>
<xi:include href="employee.xml"/>
</xforms:instance>
</xforms:model>

Limitations:

  • Files that are included with XInclude must be static: their content cannot change while the application is running. If they do, there is a risk that an older version could be used due to aggressive caching.
  • XPointer is not supported. You can only include entire documents.

Examples portal

The OXF examples are presented in a new examples portal allowing easy navigation between running examples, their description, and their source code.

XML databases support

OXF now supports XML databases using the XML:DB API and ships with the open source eXist database. New examples demonstrating this support are:

  • The "BizDoc" Example Application, a simplistic document-centric application which illustrates creating, reading, updating, and deleting (also known as CRUD operations) XML business documents from a database.
  • The XML:DB Sandbox, in which you can enter and run queries against an XML database.

For more information, please refer to the OPS Tutorial.

Resource server

The Resource Server now supports serving any URL, in addition to serving OXF resources (URLs with the form oxf:*). Additionally, case insensitive pattern matching is used for the content-type header generation.

Comments