jford       2004/04/09 09:22:14

  Added:       tutorial/xdocs/6 lifecycle.xml
  Log:
  Chapter 6 conversion to xdoc
  
  Revision  Changes    Path
  1.1                  jakarta-jetspeed/tutorial/xdocs/6/lifecycle.xml
  
  Index: lifecycle.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>
      <author email="[EMAIL PROTECTED]">David Sean Taylor</author>
      <title>Portlet Life Cycle</title>
    </properties>
  
  <body>
  
  <section name="Portlet Life Cycle">
  
  <p>
  All portlets can be automatically created when Jetspeed first starts up. 
  The default and recommended behaviour is not to create the portlets until they are 
accessed on a PSML page. 
  Once a page where a portlet exists is requested, then at this point, the portlet is 
created and added to the portlet cache.
  </p>
  
  <p>
  <source>
  <![CDATA[
  # Jetspeed can automatically create/instantiate all your Portlets
  # and place them in the cache when Jetspeed starts up. 
  autocreate.portlets=false
  ]]>
  </source>
  </p>
  
  <p>
  At the time of portlet creation, a portlet's <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/Portlet.html#init()">init()</a>
 method is called. 
  The init method is only called once, during the portlet creation phase. 
  The lifetime of a portlet is controlled by how long a portlet stays in the cache. 
  When a portlet is removed from the cache, the portlet is effectively removed from 
memory (left to the garbage collector) and is no longer accessible. 
  If a portlet is removed from the cache, and then requested again, the portlet will 
have its init method called again, since a new instance is created of the portlet. 
  Both the system administrator and programmer can control the lifetime of a portlet 
by controlling how long it lives in the cache.
  </p>
  
  <p>
  A portlet is managed through a not so well defined life cycle that defines how it is 
initialized, how it handles requests for content, and how long it lives based on 
caching behaviour described later in this section. 
  Thus you could consider there to be 3 phases in the life cycle of a portlet:
  </p>
  
  <p>
  <ul>
  <li>1. Init</li>
  <li>2.  Render</li>
  <li>3. Destroy</li>
  </ul>
  </p>
  
  <p>
  Jetspeed does support another phase in between phase 1 and 2. It is called the 
processAction phase. 
  Unfortunately, the processAction phase does not manifest itself directly in the 
portlet interface. 
  Instead, actions must be handled in action classes. 
  Action classes are inherited from Turbine, and they bleed through into the design of 
Jetspeed, coupling the Jetspeed architecture to Turbine's in a very bad way. 
  Velocity portlets attempt to rectify this design flaw, but the bottom line is that 
is still a kludge and the action processing phase is not a part of the portlet 
interface, but must be handled on another action interface. 
  We will cover actions in more depth in the section on <a 
href="../7/index.html">Velocity Portlets</a>.
  </p>
  
  <p>
  To match the phases with interface methods, we have:
  </p>
  
  <p>
  <table>
        <tr>
                <td>Phase</td>
                <td>Method</td>
        </tr>
        <tr>
                <td>Init</td>
                <td>init</td>
        </tr>
        <tr>
                <td>ProcessAction</td>
                <td>Turbine Actions</td>
        </tr>
        <tr>
                <td>Render</td>
                <td>getContent</td>
        </tr>
        <tr>
                <td>Destroy</td>
                <td>--none--</td>
        </tr>
  </table>
  </p>
  
  <p>
  During the init phase, it is recommended that you do any one-time initialisation of 
the portlet. 
  Usually this involves the initialisation of costly resources such as database 
connections or other costly activities. 
  The render phase is called per request. 
  Every time a portlet's content is requested, the getContent method is called.
  </p>
  
  <p>
  <img src="../images/image006-3.jpg"/>
  </p>
  
  <p>
  The destroy phase is dependent on the life time definition of the portlet. 
  Unfortunately, your portlet is never notified when the destroy phase occurs. 
  You can control the life time of your portlet. 
  If your portlet inherits from <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractPortlet.html";>AbstractPortlet</a>,
  then the lifetime of your portlet is controlled by how long it lives in the cache, 
and by how many instances of the portlet there are in the cache.
  </p>
  
  <p>
  First let's look at how long your portlet will live in the cache. 
  By default, this is controlled by a global portal setting for all portlets:
  </p>
  
  <p>
  <source>
  <![CDATA[
  # TimeToLive.default =
  # number of milliseconds an unused portlet will remain in cache.
  # Default 2700000 which is 45 minutes (45 * 60 * 1000)
  services.PortletCache.TimeToLive.default=2700000
  ]]>
  </source>
  </p>
  
  <p>
  The default setting is 45 minutes. 
  After a portlet has been in the cache for 45 minutes, it will be reloaded. 
  This means the init method is called again. 
  Since there is no destroy method, your portlet doesn't know when it is getting 
destroyed.
  </p>
  
  <p>
  If your portlet inherits from <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractPortlet.html";>AbstractPortlet</a>
 or <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractInstancePortlet.html";>AbstractInstancePortlet</a>,
 then your portlet is cacheable, but it will not be evicted from the cache, since the 
base implementation <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractPortlet.html";>AbstractPortlet</a>
 never allows for your portlet to expire.
  </p>
  
  <p>
  <source>
  <![CDATA[
  public Expire getExpire()
  {
  try
  {
             return ExpireFactory.getExpire( this,
                                         ExpireFactory.NO_EXPIRE );
          } catch ( JetspeedException e ) {
              Log.error( e );
              return null;
          }
      }
  }
  ]]>
  </source>
  </p>
  
  <p>
  Some portlets will expire, such as the <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/FileWatchPortlet.html";>FileWatchPortlet</a>
 and <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/NewRSSPortlet.html";>NewRSSPortlet</a>
 which uses the cache to control refreshing of its content.
  </p>
  
  <p>
  Whenever Jetspeed goes through the initialisation phase for a portlet, it will first 
check to see if the portlet already exists in the cache. 
  It does this by looking up the portlet using a unique cache handle. 
  The cache handle method can be used to control the number of instances of the same 
portlet in the cache. 
  <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractPortlet.html";>AbstractPortlet</a>
 has a method <a 
href="http://portlas.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractPortlet.html#getHandle()">getHandle</a>.
 
  For the base class, a rather odd algorithm is used to determine whether a new 
portlet instance should be created:
  </p>
  
  <p>
  <ul>
  <li>1. the URL parameter, but only if the cachedOnURL attribute is set to true</li>
  <li>2. all other parameters, both their names and values</li>
  </ul>
  </p>
  
  <p>
  The algorithm takes all of these strings and combines them to make a unique string. 
  Thus the creation of multiple instances of possibly the same portlet is controlled 
by the uniqueness of the portlets parameters. 
  This seems like a rather odd solution, but works perfectly fine if all of your 
portlets are RSS feeds, as Jetspeed was once designed but has since evolved into much 
more. 
  In the example below of an RSS portlet, the key would be combined to create: <a 
href="http://www.mozilla.org/news.rdf%7Citemdisplayed-10";>http://www.mozilla.org/news.rdf|itemdisplayed-10</a>.
 
  This isn't really very useful, since the items displayed shouldn't have any affect 
on the number of instances created of a portlet. 
  Basing the cache on the URL makes a little more sense, since we control the number 
of portlets to be equal to the number of feeds in the system.
  </p>
  
  <p>
  <source>
  <![CDATA[
      <portlet-entry name="Mozilla" hidden="false"
                     type="ref" parent="RSS" application="false">
          <meta-info>
              <title>Mozilla</title>
          </meta-info>
           <classname>org.apache.jetspeed.portal.portlets.NewRSSPortlet</classname>
          <parameter name="itemdisplayed" value="10" hidden="false"
              cachedOnName="true" cachedOnValue="true"/>
          <url cachedOnURL="true">http://www.mozilla.org/news.rdf</url>
          <category group="Jetspeed">news.software.opensource</category>
      </portlet-entry>
  ]]>
  </source>
  </p>
  
  <p>
  The <a 
href="http://portals.apache.org/jetspeed-1/apidocs/org/apache/jetspeed/portal/portlets/AbstractInstancePortlet.html";>AbstractInstancePortlet</a>
 has a different algorithm to create the uniqueness of a portlet:
  </p>
  
  <p>
  <source>
  <![CDATA[
          StringBuffer handle = new StringBuffer(256);
          handle.append(pc.getPageId());
          handle.append('/');
          handle.append(pc.getPortletId());
   
          return handle.toString(); 
  ]]>
  </source>
  </p>
  
  <p>
  New portlets are created for every portlet instance. 
  A portlet instance is defined as each instance of a portlet referenced in a PSML 
file. 
  Thus for each portlet defined on a PSML page, a new Java instance of the portlet is 
created and put in the cache with a unique handle of: PSML-PAGE-ID + PORTLET-ID. 
  The important gain with this approach is that you can now have the same portlet 
twice on the page, and those two portlets will have their own private parameters.
  </p>
  
  <p>
  This approach will have scalability issues. 
  Think about the case where each user has his own page. 
  Since we are creating new portlets for every user in the system with her own page, 
if there are thousands of simultaneous users, we have the same portlet instantiated 
thousands of time. 
  It's a waste of memory. This approach was necessary in order to rectify a bug in 
Jetspeed's design: it shares all instance parameters across all instances.
   If you find this approach to be unsatisfactory, just override the <a 
href="http://jakarta.apache.org/jetspeed/api/org/apache/jetspeed/portal/portlets/AbstractPortlet.html#getHandle()">getHandle</a>
 method for your portlet and have its uniqueness based on the name of your portlet as 
shown in the commented out method in the tutorial example (its commented out in order 
for the tutorial example in 6.3 to work properly with multiple instances of the same 
portlet):
  </p>
  
  <p>
  <source>
  <![CDATA[
      public static Object getHandle(Object config)
      {
          PortletConfig pc = null;
   
          if (!(config instanceof PortletConfig))
          {
              return null;           
          }
          return pc.getName();
      }    
  ]]>
  </source>
  </p>
  
  </section>
  </body>
  </document>
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to