XForms - Separate Deployment with Portlets

This page is obsolete and available for historical purposes only.

Availability

[SINCE: 2010-08-30]

NOTE: This feature is no longer available with Orbeon Forms 4.  See this issue for more details.

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

Comments