I have submitted a proposal for a State Manager capability for Jetspeed.
This can be found in:
proposals\StateManager.txt
For your convinence, a copy is attached.
I look forward to your comments.
- Glenn
--------------------------------------------
Glenn R. Golden, Systems Research Programmer
University of Michigan School of Information
[EMAIL PROTECTED] 734-615-1419
http://www-personal.si.umich.edu/~ggolden/
--------------------------------------------
Jetspeed Proposal: StateManager Service
Version: $Revision: 1.1 $
Proposed by: Glenn R. Golden, University of Michigan ([EMAIL PROTECTED])
Status: Proposed
Date: April 11, 2002
Overview
========
This proposes a new Jetspeed service, the "StateManager" service, which helps to
manage a certain "scope" of information related to a particular portlet instance's
interaction with a particular user. The service would be implemented as a Turbine
service with convenience wrappers placed into the Portlet API. Portlets as well as
other parts of the portal engine could keep information in this service.
The key difference between what this service provides and what other current
mechanisms provide (such as the persistence service, the registry, and the turbine
user getTemp/setTemp) is in the scope and lifetime of the information stored within.
Purpose
=======
The StateManager service is available to aid in storing transient information used by
a portlet, and scoped to each portlet instance's interaction with each user in a
specific browser window. We will call this set of information "portlet instance
state", or just "state" for short.
A "portlet instance" is a particular placement of a portlet in a particular portal
page.
If one portlet is placed twice in the same portal page, or placed in two different
portal pages, making multiple portlet instances, different states would be kept for
each instance.
If two different users are viewing the same portlet instance on the same portal page,
then different states would be kept for each user, for each portlet instance.
State is transient, and lasts only as long as the user is interacting with the portlet
instance, or, at worst, as long as the user's session is active. Once state expires,
it is discarded.
State is different from the "customization" of a portlet, which provides parameters
that a portlet instance uses for all users and is stored in the PSML document for the
portal page.
State is different from the "configuration" of a portlet, which provides parameters
that a portlet uses for all users of all instances or the portlet, and is stored in
the portlet registry.
State is different from the getTemp/setTemp mechanism in the http session, although
it's close. State provides separate name spaces for each portlet instance, but the
temp values provide only a single namespace that must be shared by all portlets and
other uses.
Potential Uses
==============
A portlet would use the portlet instance state to store any information it needs to
keep around to produce the proper content for each different user using the portlet in
each different portal page. For example, in a "wizard" style portlet, the current
step could be stored in the state. Different users using the portlet would naturally
be on different steps, so state has the correct scope for this information; the scope
of customization or configuration would not work here as it would apply to all users
or all portlet instances.
In a content management browsing portlet (like a WebDav portlet), the content
management system connection information (such as the WebDav url) may be configuration
information, shared among all users of that portlet; this may also be customization
information, shared by all users of a particular instance of the portlet. But which
folder each user is currently viewing is user specific, and portlet instance specific,
so must be kept in the portlet instance state.
One approach that portlets currently use is to store state information in hidden form
fields, so that when the user next interacts with the portlet, the state for that
particular user will be read from the form. This approach fails in a portal
environment when the user interacts with some *other* portlet on the page. The state
information hidden in form fields are not present in the form that was submitted, but
*all* portlets must provide content with each request. State must be stored in the
portal engine and available at any time to the portlet. Only portlet instance state
has the proper scope, makes the proper distinction between different portal instances
and different user sessions (and, ideally, different browser windows).
Portlet Instance State
======================
To match the format of the configuration and customization information, the state is
organized as a set of attributes; name = value pairs. Names are strings, and can be
any strings the portlet needs (the name space is separate between different portlet
instance states). Values can be any object.
State is never serialized, so the value objects live just in memory. State is cleaned
up, either explicitly by the portlet or automatically when the user's interaction
session expires. State information will not accumulate on the server past its lifetime.
State Key
=========
To achieve our desired scope, portlet instance state is keyed by:
- the session id
- the portal page id
- the portlet id
- (and ideally a unique id to distinguish different browser windows on the same portal
page in the same user session).
The key for the state is composed by the service (wrapper). The state key for a
portlet can be accessed by the portlet and used for other purposes.
For instance, the state key can be encoded in a portlet's form, so that when the form
is being processed, the portlet can ignore any forms that do not have its own unique
state key. A state key encoded in a form can enable a turbine action to handle the
form, which would not otherwise know what to do with the form fields, since at turbine
action processing time, no specific portlet has been identified.
Convenience Wrapper
====================
A convenience wrapper is built into the Portlet API, since most of the use of the
service will be in portlet code. VelocityPortletAction classes have access to the
portlet, and can use this same wrapper. Other uses of the service can find the
service using the turbine service location methods and make direct calls to it.
How to use
==========
Any Portlet can access the portlet instance state by calling on these new Portlet API
methods:
/**
* Access the named portlet instance state attribute.
* @param name The attribute name, as define by the portlet.
* @param rundata The rundata object for the current request.
* @return The named portlet instance state attribute value.
*/
public Object getStateAttrbute( String name, RunData rundata );
/**
* Set the named portlet instance state attribute value to the provided object.
* @param name The attribute name, as define by the portlet.
* @param value The value of the attribute (any object type).
* @param rundata The rundata object for the current request.
*/
public void setStateAttribute( String name, Object value, RunData rundata );
/**
* Remove the named portlet instance state attribute , if it exists.
* @param name The attribute name, as define by the portlet.
* @param rundata The rundata object for the current request.
*/
public void removeStateAttribute( String name, RunData rundata );
/**
* Remove all portlet instance state attributes.
* @param rundata The rundata object for the current request.
*/
public void clearState( RunData rundata );
/**
* Access an iterator on all names of attribute stored in the portlet instance
state.
* @param rundata The rundata object for the current request.
* @return An iterator on all names of attribute stored in the portlet instance
state.
*/
public Iterator getStateAttributeNames( RunData rundata );
/**
* Access the unique portlet instance state key.
* @param rundata The rundata object for the current request.
* @return the unique portlet instance state key.
*/
public String getStateKey( RunData rundata );
These additions to the Portlet API are implemented in AbstractPortlet, which forms the
appropriate state key for the portlet instance / user session, and provides covers
that make calls to the StateManager.
For Velocity Portlets, a portlet's processing is done in a VelocityPortletAction
class. The routines in this class are provided with a portlet, or can get one easily.
These new Portlet API methods can be invoked on this portlet to handle state.
The StateManagerService API
===========================
Direct callers of the API can find the manager using code like this:
StateManagerService mgr = (StateManagerService)TurbineServices
.getInstance()
.getService(StateManagerService.SERVICE_NAME);
The calls to the manager are like the Portlet API calls above, except that they take a
state key instead of a RunData object.
Here's the StateManager API:
// package
package org.apache.jetspeed.services.statemanager;
// imports
import java.util.Iterator;
import org.apache.turbine.services.Service;
/**
* A state manager service is...
* @version $Id: StateManager.txt,v 1.1 2002/04/11 04:15:43 taylor Exp $
*/
public interface StateManagerService
extends Service
{
/** The default control to use when none is specified */
public String SERVICE_NAME = "StateManagerService";
/**
* Access the named attribute of the keyed state.
* @param key The state key.
* @param name The attribute name.
* @return The named attribute value of the keyed state.
*/
public Object getAttribute ( String key, String name );
/**
* Set the named state attribute of the keyed state with the provided object.
* @param key The state key.
* @param name The attribute name.
* @param value The new value of the attribute (any object type).
*/
public void setAttribute( String key, String name, Object value );
/**
* Remove the named state attribute of the keyed state, if it exists.
* @param key The state key.
* @param name The attribute name.
*/
public void removeAttribute( String key, String name );
/**
* Remove all state attribute of the keyed state.
* @param key The state key.
*/
public void clear( String key );
/**
* Access an iterator on all names of attributes stored in the keyed state.
* @param key The state key.
* @return An iterator on all names of attributes stored in the keyed state.
*/
public Iterator getAttributeNames( String key );
} // interface StateManagerService
Work List
=========
To implement this proposal, the following work must be done:
- Update Portlet API with getStateAttribute, setStateAttribute, removeStateAttribute,
clearState, getStateAttributeNames, and getStateKey methods.
- Update AbstractPortlet API with new Portlet API implementations.
- Add a new StateManager service API (called:
org.apache.jetspeed.services.statemanager.StateManagerService.java)
- Add a new StateManager service implementation (called:
org.apache.jetspeed.services.statemanager.JetspeedStateManagerService.java)
- Update tr.p to include the state manager service.
- Provide Unit tests of the wrappers and the service.
- Provide example portlet (AbstractPortlet and VelocityPortlet) using the state
manager features.
- Update PortletWrapper to wrap the new Portlet API methods.
- Update BasePortletSet with a copy of the new Portlet API implementation from
AbstractPortlet.
- Update ContainerTestPortlet to satisfy the new Portlet API methods.
Browser Window Distinctions
===========================
If we want to fully support multiple browser windows for one user (in one http
session), that all can display the same portal page (perhaps different portlets
maximized, different panes selected, or all the same, but with different user
interaction state in the portlets), we need to have a unique id for each browser
window, know what that id is in the request, and use it as part of our state key.
We will look at ways to do this, but at first this service will not distinguish
between different windows.
Other uses of StateManagerService
=================================
Other than for portlet use, the StateManagerService can manage state for portal page
instances, replacing mechanisms currently in place that may not work properly when
multiple windows are opened by a user in the same http session (even if they show
different portal pages).
A portal page instance is a portal page being viewed by a user in a browser window.
Different users viewing the same portal page view different portal page instances.
State can be managed for each portal page. If two different users are viewing the
same portal page, different state would be kept for each user. If a user is viewing
two different portal pages, different states would be kept for each portal page.
The key used for portal page instance state would be
- the session id
- the portal page id
- (and ideally a unique id to distinguish different browser windows on the same portal
page in the same user session).
Once we establish portal page state, we can use it to store information we want to
keep a) separate for each portal page instance, and b) transient for the user session
only.
Maximize: When a users maximizes a portlet, this should not effect other users, nor
should it effect other browser windows the maximizing user has open on the same or
other portal pages. Same for when the user restores.
When a user maximizes a portlet, this portlet should be displayed full screen whenever
this portal page instance gets a request, but only for this particular instance of the
portal page. We can store the portlet id of the maximized portlet in the portal page
instance state.
Customize: The stack of portal elements being customized can be stored in the portal
page instance state.
Minimized: When a user minimizes a portlet, this should not effect other users! Nor
should it be remembered so that next time in the portlet is still minimized. This is
best stored in portal page instance state.
Panes: When a portal page has many panes, only one is displayed at a time. The one
displayed for one user should be independent of the one displayed for another user,
and this need not be remembered next time the user views the portal page. This can be
stored in the portal page instance state.
This work (summarized below) is made possible by the state manager proposed herein,
but is not part of nor required for this proposal.
Additional Work List
====================
- change maximize handling to use portal page instance state
- change restore handling to use portal page instance state
- change minimize handling to use portal page instance state
- change customizer stack handling to use portal page instance state
- change the pane-to-display mechanize to use the portal page instance state
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>