ate 2005/01/30 19:18:46
Modified: portals-bridges/struts/xdocs navigation.xml
Added: portals-bridges/struts/xdocs features.xml index.xml
Log:
First set of documents for the Struts Bridge: a summary and a (detailed)
features overview.
Revision Changes Path
1.2 +12 -3
jakarta-jetspeed-2/portals-bridges/struts/xdocs/navigation.xml
Index: navigation.xml
===================================================================
RCS file:
/home/cvs/jakarta-jetspeed-2/portals-bridges/struts/xdocs/navigation.xml,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- navigation.xml 29 Jul 2004 22:16:41 -0000 1.1
+++ navigation.xml 31 Jan 2005 03:18:46 -0000 1.2
@@ -15,9 +15,18 @@
limitations under the License.
-->
<project>
+
+ <title>Portals Bridges - Struts Bridge</title>
+
<body>
- <links>
- <item name="Jetspeed 2" href="../../index.html"/>
- </links>
+ <links>
+ <item name="Portlet Specification"
href="http://www.jcp.org/en/jsr/detail?id=168"/>
+ <item name="Jetspeed 2" href="../../index.html"/>
+ </links>
+
+ <menu name="Documentation">
+ <item name="Summary" href="index.html"/>
+ <item name="Features" href="features.html"/>
+ </menu>
</body>
</project>
1.1
jakarta-jetspeed-2/portals-bridges/struts/xdocs/features.xml
Index: features.xml
===================================================================
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<title>Struts Bridge Features</title>
<subtitle></subtitle>
<authors>
<person name="Ate Douma" email="[EMAIL PROTECTED]"/>
</authors>
</properties>
<body>
<section name="Features">
<p>
The Struts Bridge provides the following features for developing and
running Struts Applications as Portlets:
<ul>
<li>
<a href="#Struts Page URL">
Provides a "virtual" page context and a "normal" page url to
the Struts Application
</a>
</li>
<li>
<a href="#The ServletContextProvider interface">
Allows Servlet invocation from an ActionRequest using an
separate lightweight interface to the Portal
</a>
</li>
<li>
<a href="#Portals requiring a more complex interface">
Provides extension points if a more complex interface to the
Portal is required
</a>
</li>
<li>
<a href="#Handling ActionRequests">
Automatically separates Struts Action Processing and View
Rendering when accessed from an ActionRequest
</a>
</li>
<li>
<a href="#RenderContextAttributes to the rescue">
Transparent communication of request attributes between
ActionRequest and RenderRequests
</a>
</li>
<li>
<a href="#Rendering valid Portlet urls with the Struts JSP Tags">
Transparent translation of "normal" Web application resource
and action link urls to valid Portlet urls
</a>
</li>
<li>
<a href="#PortletRequestProcessor and
PortletTilesRequestProcessor">
Tiles support and automatic configuration of the correct
(Portlet)RequestProcessor
</a>
</li>
<li>
<a href="#Running your application as Portlet and Web Application
at the same time">
Deploy and run Struts Applications as Portlet and as Web
Application at the same time
</a>
</li>
<li>
Based on the latest official Struts release 1.2.4
</li>
</ul>
</p>
<subsection name="Struts Page URL">
<p>
Struts determines the Actions to perform on the request url. A
Portlet on the other hand doesn't
have or receive an url, only request parameters.
</p>
<p>
To be able to use Struts within a Portlet, a current Page context
is maintained by the Struts Bridge
which is used to provide Struts with a "virtual" request context
just as if it were accessed from a Web
Application.
</p>
<p>
The Struts Page URL is maintained as a Portlet
<code>RenderParameter</code> and included in all Portlet URLs
generated for the Portlet. When the <code>StrutsPortlet</code>
receives a request it uses the Struts Page URL
to create a new <code>HttpServletRequest</code> with a redefined
request url before invoking the Struts
<code>PortletServlet</code> (extending the Struts
<code>ActionServlet</code>).
</p>
<p>
None of the Action Mappings for an existing Struts Application have
to be changed (in this respect at least)
to allow it to run in a Portlet context.
</p>
</subsection>
<subsection name="The ServletContextProvider interface">
<p>
Processing <code>ActionRequest</code> and
<code>RenderRequest</code> events from a Servlet application is a
problem with the current Portlet Specification. Although Servlets
(and JSPs) can be invoked from a Portlet,
the Portlet Specification only supports this from the
<code>RenderRequest</code>.
</p>
<p>
As request parameters are only available during the
<code>ActionRequest</code>, not being able to use a Struts
for processing these is a serious limitation. Together with no
clear inter-portlet application communication
support, this is probably one of the biggest omisions from the
Portlet Specification.
</p>
<p>
But, because the Portlet Specification is build upon the Servlet
Specification (2.3), the Portlet Container
implementation (like <a
href="http://portals.apache.org/pluto">Pluto</a>) and/or the Portal itself,
usually
does have direct access to, and also uses the
<code>ServletContext</code>, even during the
<code>ActionRequest</code> event.
</p>
<p>
It is therefore usually very easy to provide access to the
<code>ServletContext</code> although it will
require knowledge about the concrete implementation of the Portal
and/or the Portlet Container.
</p>
<p>
The Struts Bridge uses the <code>ServletContextProvider</code>
interface from the Portals Bridges Common
portals-bridges-common library, to get access to the
<code>ServletContext</code> it requires.
</p>
<p>
To be able to use the Struts Bridge, a <code>StrutsPortlet</code>
must be provided with a concrete
implementation of the <code>ServletContextProvider</code> interface
(through its initialization parameters).
This implementation class can be supplied together with the Portlet
or be provided natively by the Portal as
the <a href="http://portals.apache.org/jetspeed-2">Jetspeed-2</a>
Portal does.
</p>
</subsection>
<subsection name="Portals requiring a more complex interface">
<p>
Although the <code>ServletContextProvider</code> interface has been
defined to be easily implemented for a
specific Portal, it might not be generic enough for all.
</p>
<p>
To support those kind of Portals, the <code>StrutsPortlet</code>
doesn't uses the interface directly, but only
through protected methods of its own which can be extended if
needed.
</p>
</subsection>
<subsection name="Handling ActionRequests">
<p>
During an <code>ActionRequest</code> a Portlet (or invoked Servlet)
is not allowed to write content to the
response. This is only allowed during the
<code>RenderRequest</code> event, but then a Portlet doesn't have
access anymore to the (input) request parameters which makes it
generally useless (and bad practice anyway)
for (Struts) Action processing.
</p>
<p>
Struts on the other hand only knows one request event and is
largely build upon server-side forwarding to a
JSP (or other View rendering technology) after an Action has been
processed.
</p>
<p>
The Struts Bridge solves this problem by allowing Struts Action
processing to occur during the ActionRequest.
But, as soon as Struts forwards (or includes) to another handler
(JSP, Velocity script, <em>or even another
Action></em>) it will intercept and freeze the processing.<br/>
The Struts Bridge will then save the current processing context
(like the path to include or forward to) in a
separate object, the <code>StrutsRenderContext</code>, and end the
ActionRequest.<br/>
Once the RenderRequest is invoked, the Struts Bridge will use the
<code>StrutsRenderContext</code> to restore
the state Struts (and/or an included or forwarded JSP) will expect
and continues the processing where it left
off.
</p>
<p>
Also saved in the StrutsRenderContext are the current
<code>ActionForm</code> (if it isn't already session
bounded), the <code>ActionMessages</code> and/or
<code>ActionErrors</code> (if not already session bounded
which is possible since Struts 1.2.1).
</p>
<p>
<b><em>Important:</em></b> the StrutsRenderContext is restored only
once!
</p>
<p>
The Portlet Specification expects Portlets to use a true MVC
architecture: changing the state of a Portlet is
expected to be done during ActionRequest only. The RenderRequest,
which may occur many times, is expected to
to only render the current state of the Portlet.
</p>
<p>
For a proper usage of the Struts Bridge and to conform to the
Portlet Specification requirements, the Struts
application too really should be configured to use separate Action
processing and View rendering Actions.<br/>
</p>
<p>
The dependency on the StrutsRenderContext restoring the state
during the (next) RenderRequest should be
limited to one situation only: input error processing.
</p>
<p>
When Struts encounters input validation errors, it forwards (back)
to the page specified as input for the
Action. The Struts Bridge handles this situation likewise. When it
detects ActionErrors are defined after the
ActionRequest event, it will reset the Struts Page URL to the one
from which the ActionRequest was initiated
StrutsRenderContext so subsequent (multiple) RenderRequest events
will always render that input page.
</p>
<p>
Note: this will only result the same behavior as when the Struts
Application is accessed as Web Application if
the Action Mapping input attribute indeed points to the originating
input page, which normally will be the
case.
</p>
<p>
As said, for a proper usage of the Struts Bridge, the Struts
application should be configured to use separate
Action processing and View processing Actions. The Struts Bridge
intercepts the first include or forward
initiated from a Struts Action during the ActionRequest. During
only the first following RenderRequest it will
invoke Struts with <em>the same Struts Page URL</em> as for the
ActionRequest but intercept before the actual
execution of the mapped Action and then include (never forward) the
intercepted target url of the ActionRequest
(normally a JSP).
</p>
<p>
A properly MVC configured Struts application though can (and
should) make use of a (client-side) redirect
after the Action processing Action by using an ActionForward with
redirect="true". The behavior of such an
Struts Application then truly complies to the requirements for a
Portlet. In fact, the reference
implementation of the Portlet Specification, <a
href="http://portals.apache.org/pluto">Pluto</a>, actually
sends a redirect to the client (browser) after an ActionRequest.
</p>
<p>
The Struts Bridge supports this behavior as it will intercept a
client-side redirect during an ActionRequest
by changing the Portlet Page URL to be used by subsequent
RenderRequests to the targeted redirect url.
</p>
<p>
A Struts Application not complying to the above "rules" might not
behave as expected in a Portlet context:<br/>
without this configuration a second RenderRequest event will not
get the previously saved StrutsRenderContext
restored and the invoked Struts Action will be executed again (this
time without any parameters).
</p>
<p>
Migrating an existing Struts Application to a Struts Portlet with
doesn't comply to these "rules" might seem
problematic without major changes to the code, but it doesn't have
to be.
</p>
</subsection>
<subsection name="RenderContextAttributes to the rescue">
<p>
Although a StrutsRenderContext can only be used once to communicate
request parameters from the ActionRequest
to the next RenderRequest (stored in the ActionForm), the Struts
Bridge provides another, completely
transparent, solution which can be used without any required
changes to the Struts Application.
</p>
<p>
The Struts Bridge can be configured, using a simple xml definition,
to always save specific named request
attributes during an ActionRequest and restore these only during
the next RenderRequest or optionally every
RenderRequest until the next ActionRequest or a RenderRequest for a
different Struts Page URL is invoked.
</p>
<p>
The request attribute values will be saved in the web session which
requires them to implement the
<code>Serializable</code> interface.
</p>
<p>
An example struts-portlet-config.xml (the name of this file is
configurable) definition might look like:
<source><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<config>
<render-context>
<attribute name="errors"/>
<attribute name="message" keep="true"/>
</render-context>
</config>]]></source>
<em>(This (adapted) example is taken from the JPetstore Portlet
example provided with the
<a href="http://portals.apache.org/jetspeed-2">Jetspeed-2</a>
Portal.)</em>
</p>
<p>
With the above example configuration, all request attributes named
errors and message are saved after the
ActionRequest. The errors object is restored only once, the message
object will be restored until the next
ActionRequest or when the Struts Page URL is changed.
</p>
<p>
Using the RenderContextAttributes configuration, a Struts Action
can still forward (without redirecting) to a
JSP in a Portlet while passing its required data through the
request attributes. Request scoped ActionForms
can also safely be used for this as the Struts Bridge will
automatically removes them from the session again
when they go out of scope!
</p>
<p>
Using the single use only configuration (without the keep="true"
attribute) allows one to pass on rather large
objects to the RenderRequest because, even if they are stored in
the Session, this will only be for a very
short period (milliseconds). Of course, with a subsequent
RenderRequest these objects won't be available
anymore and the specific View Renderer must be defined to handle
that situation properly.<br/>
Error objects or error messages (other than ActionMessages and
ActionErrors which are already automatically
saved in the StrutsRenderContext) are also reasonable candidates to
use like this.
</p>
</subsection>
<subsection name="Rendering valid Portlet urls with the Struts JSP
Tags">
<p>
Another problem with using Struts for Portlet Development is
rendering valid urls.
</p>
<p>
There are actually two different type of problems: urls for
resources likes images, Javascript or CSS
stylesheets which needs to be loaded by the client (browser), and
urls for interacting with the Portlet
itself.
</p>
<p>
The problem with resource urls is the fact that the content of a
Portlet is only included by the Portal,
together with possible content of other Portlets shown on the same
page. Although the Portlet runs within
its own context (the same as the web application it is based on),
the client (browser) sees only the context
of the Portal page it is currently pointed at.
</p>
<p>
A Portlet therefore cannot make use of relative src locations for a
resource url while this is perfectly valid
(mostly usually preferred) in a Web Application. For a client to be
able to retrieve a resource, its url
really must include the full context path of the Web Application.
</p>
<p>
For interacting with the Portlet special PortletURLs must be used
which can only be generated using the
Portlet API or through the Portlet JSP Tags. The Struts JSP Tags
only generate urls valid for a Web
Application and also doesn't provide some kind of URLProvider
interface like JSF.
</p>
<p>
Furthermore there are two different PortletURL types: an ActionURL
and a RenderURL.
It is very important to generate the correct type of url for a
certain interaction. Forms must *always* use
a POST to an ActionURL, but for all generated links it will have to
be determined which type of url actually
is required.
</p>
<p>
To solve these problems, the Struts Bridge provides enhanced
versions of the Struts HTML JSP Tags (including
EL variants), which take the Portlet environment into account.
Furthermore, using a separate element in
the struts-portlet-config.xml definition, specific url paths can be
configured to be of a certain type
(Resource, ActionURL, RenderURL) only.
</p>
<p>
For the enhanced Struts HTML JSP Tags (html:form, html:link,
html:rewrite, html:image and html:img), four
different TLDs are provided: a EL and non-EL variant, and for both
a full replacement of the Struts
supplied struts-html.tld as well as a separate struts-portlet.tld
containing only the enhanced Tags definitions.
</p>
<p>
The full replacement TLDs makes it very easy for migrating a Struts
Application to a Portlet context: simply
map the new TLD in web.xml or redefine the taglib uri in the JSP
using:
<source><![CDATA[
<%@ taglib
uri="http://portals.apache.org/bridges/struts/tags-portlet-html" prefix="html"
%>]]></source>
or
<source><![CDATA[
<%@ taglib
uri="http://portals.apache.org/bridges/struts/tags-portlet-html-el"
prefix="html-el" %>]]></source>
<em>(Note: the Struts Bridge library contains all the TLDs so you
don't need to add them yourself
somewhere under WEB-INF/.)</em>
</p>
<p>
For the enhanced html:link and html:rewrite Tags, three additional
boolean attributes are defined: actionURL,
renderURL and resourceURL. Using these attributes one can specify
which type of url must be generated (only
value "true" is supported).
</p>
<p>
If non of these attributes is specified (with value "true") these
Tags will by default generate a RenderURL.
</p>
<p>
But, the default can be changed (only between renderURL and
actionURL) using the struts-portlet-config.xml
definition. Furthermore, for specific url path (prefixes) you can
specify which type of url must be generated
(specifying one of the three url type attributes will always
override though).
</p>
<p>
An example struts-portlet-config.xml with portlet url type
definitions might look like:
<source><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<config>
<render-context>
<attribute name="errors"/>
<attribute name="message" keep="true"/>
</render-context>
<portlet-url-type>
<action path="/shop/add"/>
<action path="/shop/switch"/>
<action path="/shop/remove"/>
<action path="/shop/signoff"/>
<action path="/shop/viewCategory"/>
<action path="/shop/viewItem"/>
<action path="/shop/viewProduct"/>
<action path="/shop/viewCart"/>
<action path="/shop/newOrder"/>
<render path="/shop/newOrderForm"/>
<action path="/shop/listOrders"/>
<resource path="/images/"/>
</portlet-url-type>
</config>]]></source>
<em>(This is the full configuration used for the JPetstore Portlet
example provided with the
<a href="http://portals.apache.org/jetspeed-2">Jetspeed-2</a>
Portal.)</em>
</p>
<p>
In the above example the portlet-url-type element contains three
different sub elements: action, render and
resource. Their path attribute specifies the prefix to which
specific urls are matched. This matching will be
done using best match. Internally, the paths will be ordered on
longest definition first.
</p>
<p>
Not shown in the above example is the optional
default="render"|"action" attribute for the portlet-url-type
element. With it, the default type of portlet-url can be changed
from "render" to "action" as is used in the
Struts Mailreader Demo Portlet (also provided by the <a
href="http://portals.apache.org/jetspeed-2">Jetspeed-2</a>
Portal):
<source><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<config>
<portlet-url-type/>
</config>]]></source>
This feature is especially useful for Struts Applications who
were configured using an earlier version of
the Struts Bridge (0.1) which used an ActionURL as default, like
the above Struts Mailreader Demo Portlet.
</p>
<p>
The enhanced html:img and html:image Tags, as well as the html:link
and html:rewrite Tags, can be used to
generate resource urls using relative (not prefixed with a '/') src
references. The Tags will then determine
automatically determine the correct url to generate using the
current Struts Page URL as defined for this
RenderRequest.
</p>
<p>
This allows one to replace hard coded resource urls like
<source><![CDATA[<img
src="../images/struts-bridge.gif"/>]]></source>
with
<source><![CDATA[<html:image
src="../images/struts-bridge.gif"/>]]></source>
A simple change with no technical impact, but it will allow the
same JSP to be used for both a Web Application
and a Portlet. The JPetstore Portlet example as provided by <a
href="http://portals.apache.org/jetspeed-2">Jetspeed-2</a>
makes full use of this feature.
</p>
</subsection>
<subsection name="PortletRequestProcessor and
PortletTilesRequestProcessor">
<p>
The Struts Bridge requires a different RequestProcessor to be used
for the Struts Application: a <code>
PortletRequestProcessor</code>. If a Struts config doesn't define
one, or defines one which isn't based on the
PortletRequestProcessor, it will be replaced automatically by the
Struts Bridge.
</p>
<p>
The Struts Bridge also supports Tiles to be used through its
<code>PortletTilesRequestProcessor</code>. If the
TilesPlugin is defined (as required to be able to use Tiles in
Struts) it will be recognized by the Struts
Bridge and then the PortletTilesRequestProcessor will be used
instead (if not configured already).
</p>
<p>
Tiles can be used without problem within a Portlet context, even
for Action Mapping or ActionForward paths,
although the same considerations and restrictions must be taken
into account as described above.
</p>
</subsection>
<subsection name="Running your application as Portlet and Web
Application at the same time">
<p>
Although the Struts Bridge is created to allow Struts Applications
to run in a Portlet context, it also allows
the same application to be run in a Servlet context too.
</p>
<p>
If the Struts Bridge PortletServlet (which extends ActionServlet)
detects it is not accessed from a Portlet
context is simply delegates back to the underlying Struts Framework.
</p>
<p>
Provided the Struts Application doesn't use any Portlet specific
features and the Action Mapping configuration
is also (still) valid for a Web Application, the same application
war can be deployed as Web application and
as Portlet Application. When deployed in a Portal, the application
can even be accessed as Portlet or as
Web Application at the same time!
</p>
<p>
The JPetstore Portlet example provided by <a
href="http://portals.apache.org/jetspeed-2">Jetspeed-2</a> is one
example of such a "dual" mode Struts Application.
</p>
<p>
Another benefit of such a "dual" mode Struts Application is that it
can be fully tested as Web Application,
which <em>is</em> somewhat easier than testing it as a Portlet.
</p>
</subsection>
</section>
</body>
</document>
1.1 jakarta-jetspeed-2/portals-bridges/struts/xdocs/index.xml
Index: index.xml
===================================================================
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<document>
<properties>
<title>Struts Bridge Summary</title>
<authors>
<person name="Ate Douma" email="[EMAIL PROTECTED]"/>
</authors>
</properties>
<body>
<section name="Summary">
<p>
The Struts Bridge allows <a
href="http://struts.apache.org">Struts</a> and Struts Tiles applications to be
run
as <a href="http://www.jcp.org/en/jsr/detail?id=168">JSR-168</a>
compliant Portlets.
</p>
<p>
Existing or new Struts Applications can be transparently deployed as
Portlet Application or
Web Application.<br/>
The Bridge wraps and enhances the native Struts Framework to overcome
its limitations and
incompatibilities with the Java Portlet Standard requirements.
</p>
<p>
An existing Struts Application can be used as a Portlet
<em>without</em> changes to the code or JSP files if:
<ul>
<li>a few common sense rules, based on a proper MVC architecture,
are followed for the Struts Action configurations</li>
<li>Struts Tags are used for rendering all resource paths (like
images) and action links</li>
</ul>
</p>
<p>
If a Struts Portlet doesn't use Portlet specific features, it can
also be accessed and used as Web Application at
the same time. Even testing the Struts Application can then be done
completely independent of a Portal.
</p>
<p>
The Struts Bridge is developed to be independent from specific
Portals and uses only a very small interface to
the Portal to be able to get access to the Servlet environment at
runtime. As all JSR-168 Portlet Containers are
required to build upon the Servlet specification, providing this
interface for a specific Portal is usually very
easy to do, if not done already.
</p>
<p>
The Apache Portals <a
href="http://portals.apache.org/jetspeed-2">Jetspeed-2 Portal</a> provides this
interface
natively, as well as example Struts Portlet Applications using the
Struts Bridge like a JPetstore Portlet.
</p>
</section>
</body>
</document>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]