Struts Support
1. Introduction
Struts is a popular Web
Application framework, based on the MVC pattern.
In recent years, Struts has quickly gained popularity due to its ease of use and
conformance to the Model 2 pattern.
This chapter demonstrates how to use PresentationServer in conjunction with a
Struts-based Web Application in a pattern called Model
2X. It assumes that the reader is familiar with Struts.
Please refer to this page for more information
about the use of XSLT in place of JSP.
2. Control Flow
The following figure presents the flow of the request, from the client to the
Struts servlet and PresentationServer pipeline:

- HTTP Request
- Controller Servlet creates the Form Bean
- Controller Servlet calls the Action Class
- The Action Class creates and fills in the Result Bean(s)
- The Request is forwarded to the PresentationServer Servlet
- The PresentationServer Servlet serializes the Result Bean in XML
- An PresentationServer pipeline is applied on the XML Bean
- HTML is sent back to the client
3. Implementation
A Struts-PresentationServer Web Application contains two servlets: the Struts
controller server and the PresentationServer processor servlet. The former is the
default servlet, serving all URI, while the latter is bound to xpl
files and other resources served by PresentationServer (images, css, etc.). Here is
a Web Application descriptor that instantiates both servlets:
<web-app> <context-param> <param-name>oxf.resources.factory</param-name>
<param-value>org.orbeon.oxf.resources.PriorityResourceManagerFactory
</param-value> </context-param> <context-param> <param-name>oxf.resources.webapp.rootdir</param-name>
<param-value>/WEB-INF/resources</param-value>
</context-param> <context-param> <param-name>oxf.resources.priority.1</param-name>
<param-value>org.orbeon.oxf.resources.WebAppResourceManagerFactory
</param-value> </context-param> <context-param> <param-name>oxf.resources.priority.2</param-name>
<param-value>org.orbeon.oxf.resources.ClassLoaderResourceManagerFactory
</param-value> </context-param> <context-param> <param-name>oxf.properties</param-name>
<param-value>oxf:/config/properties.xml</param-value>
</context-param> <servlet> <servlet-name>struts</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param> <param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param> <load-on-startup>1</load-on-startup>
</servlet> <servlet> <servlet-name>oxf</servlet-name>
<servlet-class>org.orbeon.oxf.servlet.OXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping> <servlet-name>struts</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <servlet-mapping> <servlet-name>oxf</servlet-name>
<url-pattern>*.xpl</url-pattern>
</servlet-mapping> <servlet-mapping> <servlet-name>oxf</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping> <servlet-mapping> <servlet-name>oxf</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping> <servlet-mapping> <servlet-name>oxf</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping> <servlet-mapping> <servlet-name>oxf</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping> </web-app>
Warning
The Struts servlet
mapping parameter is set to:
org.apache.struts.action.RequestActionMapping
This instructs Struts to put the result bean in the request
rather than the session.
The Struts controller servlet interprets the request and creates form beans
containing the request parameters. It then instantiates and calls the appropriate
action class. The result bean is then set in the request, and the request is
forwarded to the PresentationServer processor servlet. Struts chooses the
forwarding pages in the same way as the traditional JSP forward: through
forward commands in the struts-config.xml file. For
example, the following fragment shows a Struts action with one possible forward, the
hello.xpl pipeline:
<action path="/hello" type="org.orbeon.oxf.struts.examples.hello.HelloAction" name="hello"> <forward name="success" path="/hello.xpl"/>
</action>
PresentationServer utilizes a Bean generator to serialize
beans from the request or session into XML. This process makes use of the Castor XML Marshaller.
The PresentationServer processor servlet is configured to use a simple pipeline
that looks at the request's path and executes the corresponding pipeline, feeding it
with the bean form generator. The pipeline's output is then processed through a
second pipeline, the epilogue. This allows to apply common stylesheets ot all pages,
such as style, internationalization, etc. The main pipeline is also responsible to
serve static resources, such as images or css style sheets. Theses resources are
served via the ResourceServer. You will find below the complete source of the Struts
main pipeline. The same file, struts.xpl is also available with the
struts examples bundled in PresentationServer distribution.
<p:config xmlns:p="
http://www.orbeon.com/oxf/pipeline"
> <p:param name="data" type="output"/>
<p:processor name="oxf:request"> <p:input name="config"> <config> <include>/request/request-path</include>
</config> </p:input> <p:output name="data" id="path"/>
</p:processor> <p:processor name="oxf:xslt"> <p:input name="config"> <xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
> <xsl:template match="/"> <config>oxf:<xsl:value-of select="substring-after(/request/request-path, '/WEB-INF')"/>
</config> </xsl:template> </xsl:stylesheet> </p:input> <p:input name="data" href="#path"/>
<p:output name="data" id="url"/>
</p:processor> <p:processor name="oxf:url-generator"> <p:input name="config" href="#url"/>
<p:output name="data" id="user-pipeline"/>
</p:processor> <p:processor name="oxf:xslt"> <p:input name="data" href="aggregate('root', #user-pipeline, #url)"/>
<p:input name="config"> <xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
> <xsl:template match="/"> <p:config> <p:param name="data" type="output"/>
<xsl:for-each select="/root/p:config/p:param[@type='input' and @name != 'errors']"> <p:processor name="oxf:bean-generator"> <p:input name="mapping"> </p:input> <p:input name="config"> <config> <attribute> <xsl:value-of select="@name"/>
</attribute> <source>request</source>
</config> </p:input> <p:output name="data" id="bean-{@name}"/>
</p:processor> </xsl:for-each> <xsl:if test="/root/p:config/p:param[@type='input' and @name = 'errors']"> <p:processor name="oxf:struts-errors-generator"> <p:output name="data" id="errors"/>
</p:processor> </xsl:if> <p:processor name="oxf:url-generator"> <p:input name="config"> <config> <xsl:value-of select="/root/config"/>
</config> </p:input> <p:output name="data" id="user-pipeline"/>
</p:processor> <p:processor name="oxf:pipeline"> <p:input name="config" href="#user-pipeline"/>
<xsl:for-each select="/root/p:config/p:param[@type='input' and @name != 'errors']"> <p:input name="{@name}" href="#bean-{@name}"/>
</xsl:for-each> <xsl:if test="/root/p:config/p:param[@type='input' and @name = 'errors']"> <p:input name="errors" href="#errors"/>
</xsl:if> <p:output name="data" ref="data"/>
</p:processor> </p:config> </xsl:template> </xsl:stylesheet> </p:input> <p:output name="data" id="pipeline"/>
</p:processor> <p:processor name="oxf:pipeline"> <p:input name="config" href="#pipeline"/>
<p:output name="data" ref="data"/>
</p:processor> </p:config>
4. Writing a Struts View Pipeline
The struts.xpl pipeline presented in the previous section acts as a
dispatcher. When the Struts servlet forwards the request to the PresentationServer
servlet, this pipeline is executed. It loads, connects and executes the view
pipeline for each page. The view pipeline must conform to the following contract:
- It
must have one
data output
-
It can have any number of input. Each input is automatically
connected to a Bean Generator, serializing a bean in the request. The name
of the input determines the name of the request or session property where
the bean is stored.
-
It can have an errors input. This input is connected to
a Struts ActionError generator. If no errors are available, an empty
errors element is generated. The error messages come from the
Struts application resources and can be internationalized. Refer to the
Struts
ActionError documentation for more information.
5. Accessing the Struts Application Resources
PresentationServer provides a mechanism to access Struts resources from an XSLT
stylesheet. You define a resource bundle in struts-config.xml, in the
message-resource element. You can declare several resource bundles by
specifying a key attribute.
<message-resources parameter="org.orbeon.oxf.struts.examples.ApplicationResources" null="false" key="messages"/>
You access the resource bundle with the struts:message() function. This
function takes 6 parameters, but only the first one is mandatory.
struts:message(key, bundle, arg0, arg1, arg2, arg3, arg4)
Parameter |
Description |
Default Value |
key |
The message key of the requested message, which must have a corresponding value in the message resources |
Mandatory |
bundle |
The name of the application scope bean under which the MessageResources object containing your messages is stored. |
Globals.MESSAGE_KEY |
arg0 |
First parametric replacement value, if any. |
null |
arg1 |
Second parametric replacement value, if any. |
null |
arg2 |
Third parametric replacement value, if any. |
null |
arg3 |
Fourth parametric replacement value, if any. |
null |
arg4 |
Fifth parametric replacement value, if any. |
null |
XSLT processors use a slightly different mechanism to access the Struts message
library. PresentationServer provides wrappers for Xalan, Saxon 6 and 7. XSLTC
calls the Java method directly. Declare the struts namespace and import
the specified stylesheet to be able to call the struts:message()
function. The table below shows the namespaces and stylesheets to import for the
supported XSLT processors.
|
Namespace |
Stylesheet |
Function |
Xalan |
http://www.orbeon.com/oxf/struts |
oxf:/oxf/struts/struts-support-xalan.xsl |
message() |
Saxon 6 |
http://www.orbeon.com/oxf/struts |
oxf:/oxf/struts/struts-support-saxon.xsl |
message() |
Saxon 7 and 8 |
http://www.orbeon.com/oxf/struts |
oxf:/oxf/struts/struts-support-saxon7.xsl |
message() |
XSLTC |
http://xml.apache.org/xalan/java/org.orbeon.oxf.util.StrutsUtils |
N/A |
messageTag() |
The following example calls the Struts support library for Xalan. It displays the
content of the page.title resource key.
<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
> <xsl:import href="oxf:/oxf/struts/struts-support-xalan.xsl"/>
<xsl:template match="/root/beans/guess"> <xhtml:html xmlns:xhtml="
http://www.w3.org/1999/xhtml"
> <xhtml:head> <xhtml:title> <xsl:value-of select="struts:message('page.title')"/>
</xhtml:title> </xhtml:head> </xhtml:html> </xsl:template> </xsl:stylesheet>
6. Using the Struts Validator
The Struts
validator allows you to write Javascript code to validate user input on the
browser. Struts uses the html:javascript tag to display the necessary
Javascript code.
Similarly, PresentationServer exposes this functionality through an XSLT function.
Only the first parameter is mandatory.
struts:javascript(formName, dynamicJavaScript, staticJavaScript, method, page)
Parameter |
Description |
Default Value |
formName |
The key (form name) to retrieve a specific set of validation rules |
Mandatory |
dynamicJavaScript |
Whether or not to render the dynamic JavaScript (boolean) |
true |
staticJavaScript |
Whether or not to render the static JavaScript (boolean) |
true |
method |
The alternate JavaScript method name to be used instead of the default one. The default is 'validate' concatenated in front
of the key (form name) passed in (ex: validateRegistrationForm)
|
null |
page |
The current page of a set of validation rules if the page attribute for the field element in the xml file is in use. |
null |
XSLT processors use a slightly different mechanism to access the Struts javascript
library. PresentationServer provides wrappers for Xalan, Saxon 6 and 7. XSLTC
calls the Java method directly. Declare the struts namespace and import
the specified stylesheet to be able to call the struts:javascript()
function. The table below shows the namespaces and stylesheets to import for the
supported XSLT processors.
|
Namespace |
Stylesheet |
Function |
Xalan |
http://www.orbeon.com/oxf/struts |
oxf:/oxf/struts/struts-support-xalan.xsl |
javascript() |
Saxon 6 |
http://www.orbeon.com/oxf/struts |
oxf:/oxf/struts/struts-support-saxon.xsl |
javascript() |
Saxon 7 and 8 |
http://www.orbeon.com/oxf/struts |
oxf:/oxf/struts/struts-support-saxon7.xsl |
javascript() |
XSLTC |
http://xml.apache.org/xalan/java/org.orbeon.oxf.util.StrutsUtils |
N/A |
javaScriptTag() |
The following example shows how to call the struts:javascript from a
simple Xalan template.
<xsl:stylesheet version="1.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
> <xsl:import href="oxf:/oxf/struts/struts-support-xalan.xsl"/>
<xsl:template match="/"> <xhtml:html xmlns:xhtml="
http://www.w3.org/1999/xhtml"
> <xhtml:head> <xhtml:script type="text/javascript"> <xsl:value-of select="struts:javascript('jsTypeForm')"/>
</xhtml:script> </xhtml:head> <xhtml:body>...
</xhtml:body> </xhtml:html> </xsl:template> </xsl:stylesheet>