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 - Using the Orbeon Forms XForms Engine with Java Applications


Introduction

Most of the example applications shipped with Orbeon Forms use the Page Flow Controller (PFC) and are implemented using components provided by Orbeon Forms such as XML pipelines. But it is also possible to use the XForms engine without worrying about these technologies and to simply use it as an XForms engine for your Java applications.

There are two main ways of integrating the Orbeon Forms XForms engine with Java applications:

  • Separately from the Orbeon Forms WAR
    • With this method, your application is deployed in its own Java web archive (WAR), and Orbeon Forms in its own WAR.

  • Together with the Orbeon Forms WAR
    • With this method, you integrate your application directly with Orbeon Forms.
    • This means that the Java JAR files and classes of your application and Orbeon Forms are deployed within the same WAR.

Both methods are documented below. Deploying separately is the recommended method.


Deployment and configuration

  Separate deployment
(recommended)
Integrated deployment
Benefits
  • Easier upgrades of both your application and Orbeon Forms.
  • Preventing situations where different versions of JAR files could conflict.
  • Cleaner application architecture.
  • No need to create your own WAR. Just use the Orbeon Forms WAR.
  • Default web.xml configuration works out of the box for JSPs.
web.xml configuration

See below for the snippet you'll want to include in your web.xml.

The value of the oxf.xforms.renderer.context parameter specifies the context into which you have deployed Orbeon Forms. By default, Orbeon forms deploys to /orbeon so this value is usually safe. If you deploy Orbeon Forms to another context, you need to change this value accordingly.

The <url-pattern> defined under the first <filter-mapping> has the value /xforms-jsp/*. This means that all the data generated by URLs starting with /xforms-jsp/ is post-processed by Orbeon Forms. You can change this value as desired.

The <url-pattern> defined under the second <filter-mapping> has the value /orbeon/*. This is necessary to allow for all Orbeon Forms resources, such as JavaScript, CSS, and Ajax server, to be accessible. This /orbeon/* value is related to the default context into which you deploy Orbeon Forms: if you change you context, you change this value as well.

See below for the snippet you'll want to include in your web.xml.

The <url-pattern> defined under the <filter-mapping> has the value /xforms-jsp/*. This means that all the data generated by URLs starting with /xforms-jsp/ is post-processed by Orbeon Forms. You can change this value as desired.

Application server configuration

Your WAR must be deployed in such a way that it is allowed forwarding requests to other web applications. With Tomcat, this is called a cross-context setup, and you enable it as follows with the crossContext attribute in server.xml:

<Context path="/my-app" docBase="/path/to/my-app/war" crossContext="true"/>

None particular: just deploy Orbeon Forms as usual.

Location of JSPs

With the default configuration shown above, all JSPs located in the directory called xforms-jsp in your WAR are processed by the XForms engine. However, it is likely that you will prefer another location. In that case, you just change the url-mapping configuration.

You must not deploy resources under the /orbeon/ directory, as that directory is reserved for Orbeon Forms resources.

With the default configuration in the Orbeon Forms web.xml, all JSPs located in the directory called xforms-jsp in your WAR are processed by the XForms engine.

Under this directory, by default you find one directory per example, for instance xforms-jsp/guess-the-number or xforms-jsp/flickr-search. You can add your own directories and JSP files as desired.

Other Java resources

You don't have to produce XForms from JSP. You can do so directly from servlets, or other Java web application frameworks (usually based on servlets and template languages). What matters is that the filter defined in web.xml kicks in for those resources and that you produce well-formed XML as output. For this to happen, you modify the <filter-mapping> accordingly to enable the filter for the URLs handled by your framework.


Session handling

All URLs are designed go through your web application's context, so your application and the Orbeon Forms XForms engine automatically share the same session.

All URLs access the same web application context, so your application and Orbeon Forms automatically share the same session.

Access control

You control security for all of your application's pages, including XForms pages, in your own application's web.xml. It is not possible to access your application's XForms pages by accessing Orbeon Forms URLs directly: your application controls the generation of XForms content, not Orbeon Forms.

However by default you can still access Orbeon Forms applications through Orbeon Forms URLs. If you don't want to deploy any Orbeon Forms applications directly, you can block external accesses to the Orbeon Forms WAR by configuring the Orbeon Forms WAR's web.xml.

You control security for all pages in the single application's web.xml.

Limitation: currently, in separate deployment, you cannot deploy your application in the default servlet context (i.e. the empty context).


web.xml configuration for separate deployment

<!-- Declare and configure the Orbeon Forms XForms filter -->
<filter>
    <filter-name>orbeon-xforms-filter</filter-name>
    <filter-class>org.orbeon.oxf.servlet.OrbeonXFormsFilter</filter-class>
    <init-param>
        <param-name>oxf.xforms.renderer.context</param-name>
        <param-value>/orbeon</param-value>
    </init-param>
</filter>
<!-- Any web resource under /xforms-jsp is processed by the XForms engine -->
<filter-mapping>
    <filter-name>orbeon-xforms-filter</filter-name>
    <url-pattern>/xforms-jsp/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- This is necessary so that XForms engine resources can be served appropriately -->
<filter-mapping>
    <filter-name>orbeon-xforms-filter</filter-name>
    <url-pattern>/orbeon/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>


web.xml configuration for integrated deployment

<filter>
    <filter-name>orbeon-xforms-filter</filter-name>
    <filter-class>org.orbeon.oxf.servlet.OrbeonXFormsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>orbeon-xforms-filter</filter-name>
    <url-pattern>/xforms-jsp/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>


Separate WAR deployment steps

You deploy Orbeon Forms as a separate WAR with the following steps:

  1. Deploy Orbeon Forms as usual, typically in the /orbeon context. Follow the installation instructions and the Orbeon Forms Tutorial if needed.
  2. Deploy your own application as a separate WAR.
  3. Copy WEB-INF/lib/orbeon-xforms-filter.jar from the Orbeon Forms WAR into your application's WEB-INF/lib/ directory.
  4. Configure your application's web.xml as described in the previous section to setup the Orbeon Forms XForms filter.
  5. Setup your application in cross-context mode, as described in the previous section.
  6. From the uncompressed orbeon.war, you can remove:
    • All the files under WEB-INF/resources, except the directory WEB-INF/resources/config and its content. (This directory contains configuration files which you might want to change, in particular the properties files.)
    • All the application-server or portal configuration files under WEB-INF; namely: jboss-web.xml, jonas-web.xml, liferay-display.xml, liferay-portlet.xml, portlet.xml, sun-web.xml, weblogic.xml. (The application-server specific files contain an example of how to declare a data source, so you can safely remove those files even if they are for the application server you are using.)
    • The WEB-INF/classes directory.
    • The WEB-INF/commons-cli-1_0.jar file.

Generating XHTML and XForms

Your JSP pages or servlets must generate well-formed XML documents that contain XHTML and XForms tags. There are two methods of passing this information to Orbeon Forms, described below.


Producing XHTML and XForms as JSP or servlet output

With this method, your JSP or servlet simply outputs XHTML and XForms in its output as it would HTML content. For example, a basic JSP page typically looks like this:

<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events">
    <xhtml:head>
        <xhtml:title>Guess The Number</xhtml:title>
        <xforms:model>
            <xforms:instance>...</xforms:instance>
        </xforms:model>
    </xhtml:head>
    <xhtml:body>
        <xhtml:h1>My Page</xhtml:h1>
        <xforms:input ref="..."/>...
    </xhtml:body>
</xhtml:html>

When using JSP, you can then use JSP tags as usual to produce your XHTML and XForms page as you would a regular HTML page.


Passing XHTML and XForms as a request attribute

With this method, the output of your JSP or servlet is ignored by Orbeon Forms. Instead, you set an attribute into the HttpServletRequest object which is passed to servlets (and also accessible in JSP through the request variable):

request.setAttribute("oxf.xforms.renderer.document", xformsDocument);

The name of the attribute must be "oxf.xforms.renderer.document". It may contain XHTML and XForms as an XML Document Object Model (DOM), as a dom4j Document, or as a String containing XML.


File inclusions with separate deployment

When you deploy your XForms in the Orbeon Forms resources directory, you can reference instances in separate files from your XForms with: <xforms:instance src="oxf:/path/file.xml"/>. You can also use XInclude to include arbitrary parts of your form with: <xi:include href="oxf:/path/file.xml"/>. The oxf: scheme tells Orbeon Forms that the file is loaded from the resource directory, typically from WEB-INF/resources inside the Orbeon Forms war file.

You could do this in separate deployment as well, but you would need to put the files to include in the Orbeon Forms resource directory. Since that resource directory is typically inside the Orbeon Forms war file, doing so would defeat the purpose of using separate deployment.

For instances, you could use a relative URL such as <xforms:instance src="file.xml"/>. If the URL for your form is http://localhost/myapp/forms/registration.jsp, then Orbeon Forms will load the file to include from http://localhost/myapp/forms/file.xml. Most likely this will work, but you will incur the cost of an additional HTTP request every time the page is loaded.

So instead, you will want to use an inclusion mechanism native to the template language you are using in your application. If you write JSP, use the include directive. To include an instance, use:

<xforms:instance id="my-instance">
    <%@include file="file.xml"%>
</xforms:instance>
You can use the include directive in the same way to include an arbitrary part of your form stored in a separate file:

<xhtml:body>
    <!-- Part of the form inline. -->
    <xhtml:div>
        ...
    </xhtml:div>
    <!-- Part of the form stored in a spearate file -->
    <%@include file="part.xhtml"%>
</xhtml:body>

Processing model

What happens when your JSP or servlet produces an XHTML and XForms document?

  • If configured appropriately in web.xml, the Orbeon Forms XForms filter kicks in and intercepts the output of your JSP or servlet (whether produced the regular way or passed as a request attribute).
  • The Orbeon Forms XForms filter then forward the request to Orbeon Forms, at the location /xforms-renderer.
  • Orbeon Forms reacts to /xforms-renderer by extracting the XHTML and XForms document from the forwarded request.
  • Orbeon Forms sends the XHTML and XForms document to the standard Orbeon Forms epilogue called /config/epilogue-servlet.xpl. The epilogue performs several tasks, including transforming XHTML and XForms into HTML that the browser can understand. The default configuration of this pipeline should be fine for most use cases, which means you usually don't need to worry about it.

Note that the epilogue applies the default theme under /config/theme-plain.xsl. However, it does not perform further URL rewriting by default.


Using a Spring or Struts controller

Orbeon Forms does not specifically support third-party controllers such as the Spring or Struts controllers, but you can use such controller with the Orbeon Forms XForms engine in separate deployment mode.

With a separate controller, the workflow work like this:
  1. Your controller initially calls up a page, e.g. a JSP page, producing XHTML+XForms.
  2. The Orbeon XForms filter handle the output of your page, and processes the XForms contents.
  3. The XForms page, using <xforms:submission>, POSTs or PUTs data (through HTTP or a servlet forward) to your controller.
  4. The controller makes the decision as to what’s next, e.g. it can run another JSP producing XHTML+XForms.
  5. Go back to step 1.

Accessing submitted XML data

Orbeon Forms supports the input:instance URI to access XML data submitted to the current page:

<xforms:instance id="input" src="input:instance"/>

This allows you to implement scenarios like this one:
  1. JSP page is accessed through HTTP GET
    1. Page generates XForms
    2. XForms is processed by the Orbeon filter and XForms engine
    3. HTML is sent to the browser
  2. User performs action on page
    1. XForms server performs a submission to another JSP page, submitting XML through the HTTP POST or PUT method
  3. New JSP page is accessed through HTTP POST or PUT
    1. Page generates XForms
    2. XForms is processed by the Orbeon filter and XForms engine
    3. XForms engine has access to the submitted XML data through the input:instance URI
    4. HTML is sent to the browser
NOTE: In separate deployment, you can use input:instance only if your JSP or servlet has not attempted to read the request body first!

Attributes set by the Orbeon Forms filter

As of 2009-10, the Orbeon Forms filter implemented by OrbeonXFormsFilter sets the following request attributes:

Property name Value type Function
oxf.xforms.renderer.deployment
"integrated" | "separate"
  • whether deployment is integrated or separate
  • this is passed for Orbeon Forms resources as well as documents
oxf.xforms.renderer.base-uri
path
  • contains request path, i.e. /xforms-jsp/guess-the-number/test.jsp
  • used for xml:base resolution by XForms
oxf.xforms.renderer.document
XHTML document as string

 the document must contain well-formed XML

oxf.xforms.renderer.content-type
content-type

content-type of the document passed

oxf.xforms.renderer.has-session
"true" | "false"

whether the filter sees an existing session or not

NOTE: In general, you do not need to know about these properties to use the Orbeon Forms filter.


Implementing XForms services with JSP

The backend of your forms is usually best implemented with "services" which can be called with <xforms:submission>. Most of the time, XML is being posted to the service and XML is returned by the service. Since services take XML as input and generate XML, XML pipelines are an ideal tool to implement services.

However, you can also implement simple services directly with JSP. To produce XML output, your JSP page has to set the appropriate content type for the response with:

response.setContentType("application/xml")

To read XML input, you can create an object that represents the input document using the dom4j API:

Document queryDocument = xmlReader.read(request.getInputStream())

You then use this object to gather data about the query sent to your service.

In XForms you reference the service with the action attribute of <xforms:submission>:

<xforms:submission id="do-query"
   
ref="instance('query')" method="post"
    replace="instance" instance="photos"
    resource="/xforms-jsp/flickr-search/service-search.jsp"/>