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]

Reply via email to