[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>
<!-- Map the Orbeon portlet XForms filter -->
<filter-name>orbeon-forms-portlet-xforms-filter</filter-name>
<portlet-name>MY-PORTLET-NAME</portlet-name>
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-name>orbeon-trampoline-servlet</servlet-name>
<servlet-class>org.orbeon.oxf.portlet.OrbeonTrampolineServlet</servlet-class>
<param-name>oxf.xforms.renderer.context</param-name>
<param-value>/orbeon</param-value>
<load-on-startup>1</load-on-startup>
<servlet-name>orbeon-trampoline-servlet</servlet-name>
<url-pattern>/xforms-trampoline</url-pattern>
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&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-name>orbeon-filter-sample-portlet</portlet-name>
<portlet-class>org.orbeon.oxf.portlet.OrbeonPortletFilterSample</portlet-class>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<name>oxf.main-processor.name</name>
<value>{http://www.orbeon.com/oxf/processors}pipeline</value>
<name>oxf.main-processor.input.config</name>
<value>oxf:/config/prologue-portlet.xpl</value>
<name>oxf.error-processor.name</name>
<value>{http://www.orbeon.com/oxf/processors}pipeline</value>
<name>oxf.error-processor.input.config</name>
<value>oxf:/config/error.xpl</value>
<title>Orbeon Forms Filter Sample Portlet</title>
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