This document explains how to modify an existing installation of Orbeon OPS as a WebApp in Tomcat so that another WebApp can forward XHTML+XForms documents to Orbeon OPS, without changing the URL of the original WebApp.
This document is intended to help estimate the level of effort required to put these changes into Orbeon OPS.
These changes:
OPS has over 40 JAR files in it, including old and variant versions of commonly used packages. Putting OPS in its own WebApp gives Orbeon OPS its own Java ClassLoader and isolates other WebApps using it from Orbeon's dependencies, which might otherwise have conflicts.
I got the following from Adrian Baker:
The rest I figured out myself, by consulting the Tomcat documentation and the Orbeon OPS Source.
Almost. There are a couple of unsolved problems:
f:url-norewrite="true"
declaration on the
link to Orbeon's home page. It doesn't seem reasonable to have to decorate every hyperlink in my XHTML+XForms text with f:url-norewrite="true"
, so there needs to be some other solution to making this work. I'm not even sure what the re-writing is for; this area is a big
hole in my understanding.ORBEON.xforms.Globals.formStaticState[formIndex] has no properties xforms.js (line 1615)
Or, instead of rebuild, do this:
$ javac -g -cp c:/path/to/tomcat/webapps/ops/WEB-INF/lib/ops.jar c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/src/java/org/orbeon/oxf/xforms/processor/handlers/XHTMLHeadHandler.java $ javac -g -cp c:/path/to/tomcat/webapps/ops/WEB-INF/lib/ops.jar\;c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/lib/log4j-1.3alpha0.jar\;c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/lib/servlet-2_3-4_0_4.jar\;c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/lib/commons-fileupload-1.0.jar c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/src/java/org/orbeon/oxf/servlet/ServletExternalContext.java $ mkdir -p c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/classes/org/orbeon/oxf/servlet/ $ cp c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/src/java/org/orbeon/oxf/servlet/ServletExternalContext*.class c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/classes/org/orbeon/oxf/servlet/ $ mkdir -p c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/classes/org/orbeon/oxf/xforms/processor/handlers $ cp c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/src/java/org/orbeon/oxf/xforms/processor/handlers/XHTMLHeadHandler*.class c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/classes/org/orbeon/oxf/xforms/processor/handlers $ cd c:/path/to/Orbeon/ops-cvs-2007-01-26/orbeon/classes $ jar uvf c:/path/to/tomcat/webapps/ops/WEB-INF/lib/ops.jar .
$ cd c:/path/to/patched/resources/ $ jar uvf c:/path/to/tomcat/WEB-INF/lib/ops-resources-public.jar ops/javascript/xforms-min.js $ jar uvf c:/path/to/tomcat/WEB-INF/lib/ops-resources-public.jar ops/javascript/xforms.js
*** orig/ops-cvs-2007-01-26/orbeon/src/examples/web/ops/javascript/xforms.js Thu Nov 9 12:15:46 2006
--- ops-cvs-2007-01-26/orbeon/src/examples/web/ops/javascript/xforms.js Wed Jan 31 14:32:07 2007
! var PATH_TO_JAVASCRIPT = "/ops/javascript/xforms.js";
------
! var WEBAPP_PREFIX="/MYWEBAPP/MYSERVLET/ops";
! var PATH_TO_JAVASCRIPT = WEBAPP_PREFIX + "/ops/javascript/xforms.js";
--- ops-cvs-2007-01-26/orbeon/src/java/org/orbeon/oxf/servlet/ServletExternalContext.java Tue Jan 30 16:50:00 2007
*** orig/ops-cvs-2007-01-26/orbeon/src/java/org/orbeon/oxf/servlet/ServletExternalContext.java Mon Dec 11 17:27:16 2006
public String getContextPath() {
! return nativeRequest.getContextPath();
}
------
public String getContextPath() {
! return "/MYWEBAPP/MYSERVLET" + nativeRequest.getContextPath();
}
*** web.xml~ Tue Jan 16 11:29:54 2007 --- web.xml Thu Feb 1 10:01:59 2007 <load-on-startup>3</load-on-startup> </servlet> + <!-- From Adrian Baker [adrian.baker@orionhealth.com] --> + <servlet> + <!-- Handles initial display of a form. --> + <servlet-name>ops-render-servlet</servlet-name> + <servlet-class>org.orbeon.oxf.servlet.OPSServlet</servlet-class> + <!-- Set main processor --> + <init-param> + <param-name>oxf.main-processor.name</param-name> + <param-value>{http://www.orbeon.com/oxf/processors}pipeline</param-value> + </init-param> + <init-param> + <param-name>oxf.main-processor.input.config</param-name> + <param-value>oxf:/render-form-from-request.xpl</param-value> + </init-param> + </servlet> + <!-- End of code from Adrian Baker [adrian.baker@orionhealth.com] --> <!-- Uncomment this for the SQL examples --> <!-- *************** </servlet>--> <!-- End SQL examples --> + <servlet-mapping> + <servlet-name>ops-render-servlet</servlet-name> + <url-pattern>/ops-render-servlet</url-pattern> + </servlet-mapping> <servlet-mapping> <servlet-name>ops-main-servlet</servlet-name>
<?xml version="1.0"?> <!-- From Adrian Baker [adrian.baker@orionhealth.com] The OPSServlet forwarded to is configured to run a simple pipeline which uses the scope generator to extract the request attribute and pass it to the standard epilogue pipeline request.setAttribute("xform", <XHTML+XForms DOM>); getServletConfig().getServletContext().getContext("/ops").getRequestDispatcher("/ops-render-servlet").forward(request, response) --> <p:config xmlns:p="http://www.orbeon.com/oxf/pipeline" xmlns:oxf="http://www.orbeon.com/oxf/processors"> <p:processor name="oxf:scope-generator"> <p:input name="config"> <config> <key>xform</key> <scope>request</scope> </config> </p:input> <p:output name="data" id="extracted-xform"/> </p:processor> <p:processor name="oxf:pipeline"> <p:input name="config" href="config/epilogue.xpl"/> <p:input name="data" href="#extracted-xform"/> <p:input name="instance"><x/></p:input> <p:input name="xforms-model"><x/></p:input> </p:processor> </p:config>
if (isOpsRequest(request)) { String ops ="/ops"; String srv=request.getPathInfo().substring(ops.length()); ServletContext opsContext = getServletConfig().getServletContext().getContext(ops); if (opsContext == null) throw new RuntimeException("can't find Orbeon context; tomcat /MYWEBAPP webapp is missingwhere"); RequestDispatcher dispatcher = opsContext.getRequestDispatcher(srv); if (dispatcher == null) throw new RuntimeException("can't find Orbeon request dispatcher"); dispatcher.forward(request, response); // forward this back-channel directly. return; }
private boolean isOpsRequest(HttpServletRequest request) { String path = request.getPathInfo(); return (path != null && path.startsWith("/ops/")); }
String ops ="/ops";
String srv="/ops-render-servlet";
ServletContext opsContext = getServletConfig().getServletContext().getContext(ops);
if (opsContext == null) throw new RuntimeException("can't find Orbeon context; tomcat /MYWEBAPP webapp is missing <Context crossContext='true' />");
RequestDispatcher dispatcher = opsContext.getRequestDispatcher(srv);
if (dispatcher == null) throw new RuntimeException("can't find Orbeon request dispatcher");
// From Adrian Baker [adrian.baker@orionhealth.com]
request.setAttribute("xform", domDocument);
dispatcher.forward(request, response);
tomcat/conf/server.xml
.
If you don't do this, your webapp will get null for RequestDispatcher.
<!-- Define the default virtual host --> <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true" autoDeploy="true"> + <Context path="/MYWEBAPP" docBase="C:\path\to\tomcat\webapps\MYWEBAPP" crossContext="true"/>
*** orig/ops-cvs-2007-01-26/orbeon/src/resources/config/epilogue-servlet.xpl Fri Jan 12 07:12:10 2007
--- ops-cvs-2007-01-26/orbeon/src/resources/config/epilogue-servlet.xpl Thu Feb 1 09:31:49 2007
<!-- Apply theme -->
<p:choose href="#request">
! <p:when test="starts-with(/request/request-path, '/doc/') or /request/parameters/parameter[name = 'orbeon-theme']/value = 'plain'">
<p:processor name="oxf:unsafe-xslt">
<p:input name="data" href="#xformed-data"/>
------
<!-- Apply theme -->
<p:choose href="#request">
! <p:when test="true() or starts-with(/request/request-path, '/doc/') or /request/parameters/parameter[name = 'orbeon-theme']/value = 'plain'">
<p:processor name="oxf:unsafe-xslt">
<p:input name="data" href="#xformed-data"/>
UNTESTED: I'm not sure this is necessary but I put the constant prefix into src and href attributes in theme-plain.xsl. I suspect URL-rewriting interacts with this.
*** orig/ops-cvs-2007-01-26/orbeon/src/resources/config/theme-plain.xsl Fri Jan 12 07:12:10 2007
--- ops-cvs-2007-01-26/orbeon/src/resources/config/theme-plain.xsl Thu Feb 1 09:32:19 2007
('xforms-help-image',
(for $c in tokenize(@class, ' ') return if ($c = 'xforms-help') then () else $c))"/>
! <xhtml:img alt="Help" title="" src="/ops/images/xforms/help.gif" class="{string-join($image-class, ' ')}"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
------
('xforms-help-image',
(for $c in tokenize(@class, ' ') return if ($c = 'xforms-help') then () else $c))"/>
! <xhtml:img alt="Help" title="" src="/MYWEBAPP/ops/images/xforms/help.gif" class="{string-join($image-class, ' ')}"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
UNTESTED: Same as above for xforms-to-xhtml.xsl.
*** orig/ops-cvs-2007-01-26/orbeon/src/resources/config/xforms-to-xhtml.xsl Sun Nov 19 14:24:40 2006 --- ops-cvs-2007-01-26/orbeon/src/resources/config/xforms-to-xhtml.xsl Thu Feb 1 09:32:51 2007 ! <xhtml:input type="image" class="calendar-button" src="/ops/images/xforms/calendar.gif" value="Date" onclick="showCalendar('', '{$id}'); return false;"/> <xsl:if test="not(preceding::xforms:input[@xxforms:type = '{http://www.w3.org/2001/XMLSchema}date'])"> ------ ! <xhtml:input type="image" class="calendar-button" src="/MYWEBAPP/ops/images/xforms/calendar.gif" value="Date" onclick="showCalendar('', '{$id}'); return false;"/> *************** ! <xhtml:img src="/ops/images/xforms/help.gif" onclick="var w = window.open('', '_blank', 'height=150,width=250,status=no,toolbar=no,menubar=no,location=no,dependent=yes'); ------ ! <xhtml:img src="/MYWEBAPP/ops/images/xforms/help.gif" onclick="var w = window.open('', '_blank', 'height=150,width=250,status=no,toolbar=no,menubar=no,location=no,dependent=yes');