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 - Separate Deployment with Portlets

[SINCE: 2010-08-30]

Purpose

In order to reduce the complexity of bundling Orbeon Forms within your own portlet application, Orbeon Forms supports deploying Orbeon Forms as a web application separate from your portlet application.

NOTE: This has been tested with Liferay version 6.0.5 only.

How it works

When Orbeon is deployed in this mode, your portlet simply outputs XHTML+XForms content, which is then automatically delegated to Orbeon Forms for XForms rendering..

Configuration

Overview

  • deploy the Orbeon Forms WAR (orbeon.war) into your portal
  • enable cross-context access to orbeon.war
  • in your portlet application:
    • include orbeon-xforms-filter.jar
    • configure OrbeonPortletXFormsFilter as a portlet filter around the portlets that produce XForms
    • configure OrbeonTrampolineServlet as a servlet mapped to /xforms-trampoline

portlet.xml configuration

Here is how you define and map the Orbeon portlet XForms filter in your portlet.xml file:

<!-- Define the Orbeon portlet XForms filter (for handling XForms within your own portlets) -->
<filter>
    <filter-name>orbeon-forms-portlet-xforms-filter</filter-name>
    <filter-class>org.orbeon.oxf.portlet.OrbeonPortletXFormsFilter</filter-class>
    <lifecycle>RENDER_PHASE</lifecycle>
    <lifecycle>ACTION_PHASE</lifecycle>
    <lifecycle>RESOURCE_PHASE</lifecycle>
</filter>

<!-- Map the Orbeon portlet XForms filter -->
<filter-mapping>
    <filter-name>orbeon-forms-portlet-xforms-filter</filter-name>
    <portlet-name>MY-PORTLET-NAME</portlet-name>
</filter-mapping>

In this example, you have to replace MY-PORTLET-NAME with the name of your portlet that produces XForms.

web.xml configuration

Here is how you define and map the Orbeon trampoline servlet in your web.xml file:

<servlet>
    <servlet-name>orbeon-trampoline-servlet</servlet-name>
    <servlet-class>org.orbeon.oxf.portlet.OrbeonTrampolineServlet</servlet-class>
    <init-param>
        <param-name>oxf.xforms.renderer.context</param-name>
        <param-value>/orbeon</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>orbeon-trampoline-servlet</servlet-name>
    <url-pattern>/xforms-trampoline</url-pattern>
</servlet-mapping>

Here, the value of the oxf.xforms.renderer.context parameter must be the context of the separately-deployed Orbeon WAR, typically /orbeon.

Tomcat-specific configuration

With a Liferay-Tomcat setup, to enable cross-context, one way is to create context files under $TOMCAT_ROOT/conf/Catalina/localhost (adjusting "Catalina" and "localhost" to your local configuration if needed):

orbeon.xml:

<Context path="/orbeon" crossContext="true"/>

my-app.xml:

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


Where my-app is the context where your application is deployed.

You can also update $TOMCAT_ROOT/conf/server.xml by adding:

<Host>
    <Context path="/orbeon" docBase="orbeon" crossContext="true"/>
    <Context path="/my-app" docBase="my-app" crossContext="true"/>

XForms submissions

In this deployment mode, you can run XForms submissions that target your portlet. Your portlet receives the submission as an action request. To enable such submissions:
  • use replace="all"
  • use a relative URL as submission resource
  • specify on the submission resource URL the portlet render parameters you want to set if any
  • optionally, POST a body to make available to the action request
Example:

<xf:submission ref="instance()" method="post" resource="/?p1=42&amp;p2=foobar" replace="all">

Render parameters for your portlet are changed as follows:
  • The portlet request receives render parameters updated with the parameters of the submission.
  • Existing parameters (based on the parameter name) are replaced (as opposed to appended)
  • The portlet's render parameter are updated so that they are made available to subsequent portlet requests
NOTE: In this mode, submissions with absolute URLs are not supported yet.

Limitations

As 2010-10-10, with Liferay, if your portlet produces content with JSP, it seems that the filter is unable to filter the content of the portlet. This might be a Liferay bug. See:
As workarounds your portlet:
  • can produce content directly by writing into its output
  • can store content as a string into the oxf.xforms.renderer.document request parameter

Sample Portlet

[SINCE: 2010-10-10]

Orbeon features a very simple sample portlet that can be used to test separate deployment. , configured as follows:

<portlet>
    <portlet-name>orbeon-filter-sample-portlet</portlet-name>
    <portlet-class>org.orbeon.oxf.portlet.OrbeonPortletFilterSample</portlet-class>
    <supports>
        <mime-type>text/html</mime-type>
        <portlet-mode>view</portlet-mode>
    </supports>
    <init-param>
        <name>oxf.main-processor.name</name>
        <value>{http://www.orbeon.com/oxf/processors}pipeline</value>
    </init-param>
    <init-param>
        <name>oxf.main-processor.input.config</name>
        <value>oxf:/config/prologue-portlet.xpl</value>
    </init-param>
    <init-param>
        <name>oxf.error-processor.name</name>
        <value>{http://www.orbeon.com/oxf/processors}pipeline</value>
    </init-param>
    <init-param>
        <name>oxf.error-processor.input.config</name>
        <value>oxf:/config/error.xpl</value>
    </init-param>
    <portlet-info>
        <title>Orbeon Forms Filter Sample Portlet</title>
    </portlet-info>
</portlet>

Technical details

Render and resource requests

With separate deployment, the data flows as follows:
  • a Portlet filter, OrbeonPortletXFormsFilter,  intercepts the output of your portlet, namely:
    • render requests
    • resource requests for Orbeon resources
  • OrbeonPortletXFormsFilter forwards the request and the intercepted output to a servlet located within your portlet application, OrbeonTrampolineServlet
  • OrbeonTrampolineServlet forwards the request to the Orbeon Forms web application
  • the Orbeon Forms XForms renderer produces the output that show in the portlet, including:
    • prefixing ids with the portlet namespace
    • rewriting render, action and resources URLs
The reason for OrbeonTrampolineServlet is that the portlet request dispatcher does not seem to be able to target a separate servlet context.

With this configuration, request for Orbeon-specific resources are portlet resources requests and directed to your portlet. This includes:
  • Orbeon Forms CSS and JavaScript files
  • the Orbeon Forms Ajax server

Action requests

The filter also intercepts action requests. For requests targeted at Orbeon, namely for a form post to /xforms-server-submit (second-pass of a submission with replace="all"), special processing takes place:
  • the filter forwards the request to Orbeon; as per the portlet spec, no response body can be produced by this forward
  • Orbeon completes the second pass of the submission using the FilterPortletSubmission strategy
  • request path, parameters, body, mediatype, and method are set into the request
  • after forward() completes, the filter obtains the request parameters
    • it sets render parameters from the path/parameters if present
    • it wraps an ActionRequest with the body if present
    • the request's render parameters include the parameters specified on the submission, if any
    • it runs doFilter() to let the portlet handle the body and new render parameters
  • a new render request sent by the portal causes the portlet to use the updated render parameters