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]