We solved the problem described in <http://bugs.sakaiproject.org/confluence/pages/viewpage.action?pageId=4981&showComments=true>. Here is our solution to implement "request thread" scope.

This sollution is actually JSF independent. We apply it to handlers. Handlers are defined as managed bean in session scope, and implement Removable and Skimmable, when appropriate.


Readers can consider this a release under the Apache License.


==================================================================

package be.peopleware.servlet.sessionMopup;


/**
* <p>Objects of this type can signal that they want to be removed from
* a collection. They are queried at some times, and if [EMAIL PROTECTED] #isToBeRemoved()}
* return <code>true</code>, they will be removed from that collection.</p>
* <p>The [EMAIL PROTECTED] MopupListener} applies this to all variables in
* session scope of a web application at the end of a HTTP request.</p>
*
* @author Jan Dockx
* @author PeopleWare n.v.
*/
public interface Removable {

/*<section name="Meta Information">*/
//------------------------------------------------------------------
/** [EMAIL PROTECTED] */
public static final String CVS_REVISION = "$Revision: 1.1 $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_DATE = "$Date: 2005/08/25 13:56:47 $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_STATE = "$State: Exp $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_TAG = "$Name: $"; //$NON-NLS-1$
/*</section>*/


/**
* Return <code>true</code> if <code>this</this</code> wants to be removed
* from the collection at this time.
*/
boolean isToBeRemoved();

}

==================================================================

package be.peopleware.servlet.sessionMopup;


import java.io.Serializable;


/**
* <p>Objects of this type have data that should be cleared at certain times
* or under certain conditions (the fat should be skimmed of them). At
* certain times, [EMAIL PROTECTED] #skim()} will be called on objects of this type.
* The implementation of this method then decides if skimming is appropriate
* at this time, given the state of <code>this</code>instance, what should
* be skimmed, and what <def>skimming</def> entails in these circumstances.
* Potentially, the implementation can cascade the skimming request to related
* objects.</p>
* <p>The [EMAIL PROTECTED] MopupListener} applies this to all variables in
* session scope of a web application at the end of a HTTP request.</p>
* <p>If an instance of this type is also [EMAIL PROTECTED] Serializable} it is good
* practice to surely skim transient fields.</p>
*
* @author Jan Dockx
* @author PeopleWare n.v.
*/
public interface Skimmable {

/*<section name="Meta Information">*/
//------------------------------------------------------------------
/** [EMAIL PROTECTED] */
public static final String CVS_REVISION = "$Revision: 1.1 $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_DATE = "$Date: 2005/08/25 13:56:47 $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_STATE = "$State: Exp $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_TAG = "$Name: $"; //$NON-NLS-1$
/*</section>*/


/**
* Skim unneeded data from this instance, if applicable at this time.
*/
void skim();

}

==================================================================

package be.peopleware.servlet.sessionMopup;


import java.io.Serializable;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
* <p>Mopup information in session scope on the destruction of a HTTP request. For
* all variables in session scope, first we check if they are
* [EMAIL PROTECTED] Removable#isToBeRemoved() to be removed}.
* If so, the variable is removed from session scope. If not, we check if they
* are [EMAIL PROTECTED] Skimmable}. If so, they are [EMAIL PROTECTED] Skimmable#skim() skimmed}.</p>
* <p>It makes no sense to do this for request scope, since the entire request
* scope will be discarded at the end of the HTTP request. It makes no sense
* to do this for application scope, since objects in application scope
* should not depend on the actions of a specific user.</p>
* <p>This listener is called on initialize and destroy of a request. This listener
* is to be registered with the web application in the <kbd>web.xml</kbd> file.</p>
* <pre>
* &lt;listener&gt;
* &lt;listener-class&gt;be.peopleware.servlet.sessionMopup.MopupListener&lt;/listener-class&gt;
* &lt;/listener&gt;
* </pre>
*
* @author Jan Dockx
* @author PeopleWare n.v.
*/
public class MopupListener implements ServletRequestListener, Serializable {

/* <section name="Meta Information"> */
//------------------------------------------------------------------

/** [EMAIL PROTECTED] */
public static final String CVS_REVISION = "$Revision: 1.3 $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_DATE = "$Date: 2005/09/07 21:38:48 $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_STATE = "$State: Exp $"; //$NON-NLS-1$
/** [EMAIL PROTECTED] */
public static final String CVS_TAG = "$Name: $"; //$NON-NLS-1$

/* </section> */

private static final Log LOG = LogFactory.getLog(MopupListener.class);

// Serializability ok: no instance state

/**
* Do nothing
*/
public void requestInitialized(final ServletRequestEvent event) {
// NOP
}

/**
* Check all session scope variables. If the value of the variable
* implements [EMAIL PROTECTED] Removable}, remove the variable from session scope if
* [EMAIL PROTECTED] Removable#isToBeRemoved()} returns <code>true</code>. If the
* variable is not removed, check if the value of the variable implements
* [EMAIL PROTECTED] Skimmable}. If so, [EMAIL PROTECTED] Skimmable#skim()} that object.
*/
public void requestDestroyed(final ServletRequestEvent event) {
LOG.debug("starting after-HTTP-request mopup");
try {
HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
// ClassCastException
assert request != null : "request cannot be null";
HttpSession session = request.getSession(false);
if (session != null) {
List attributeNames = new LinkedList();
{ /* put all the names in a list; copy is needed to avoid
concurrent modification problems if things are removed
while we are iterating over the set */
Enumeration enumeration = session.getAttributeNames();
// IllegalStateException if session is invalidated
while (enumeration.hasMoreElements()) {
attributeNames.add(enumeration.nextElement());
// certainly a String
}
}
{ /* iterate over the names, get the value; if the value
is instance of Removable, ask it if it wants to be removed;
if so, remove. If it is not Removable or doesn't want
to be removed, check if it is Skimmable; if so,
skim it */
Iterator iter = attributeNames.iterator();
while (iter.hasNext()) {
String attrName = (String)iter.next();
Object value = session.getAttribute(attrName);
// IllegalStateException if session is invalidated
LOG.debug("looking at attribute \"" + attrName + "\" = " + value);
if (value != null) {
if ((value instanceof Removable) && ((Removable)value).isToBeRemoved()) {
LOG.debug("attribute \"" + attrName + "\" is to be removed");
session.removeAttribute(attrName);
// IllegalStateException if session is invalidated
}
else if (value instanceof Skimmable) {
LOG.debug("attribute \"" + attrName + "\" is to be skimmed");
((Skimmable)value).skim();
}
else {
LOG.debug("attribute \"" + attrName + "\" is not to be removed nor skimmed");
}
}
}
}
}
else {
LOG.debug("no session found; nothing to do");
}
}
catch (ClassCastException ccExc) {
LOG.fatal("Servlet request was not an HttpServletRequest. This listener " +
"only makes sense in the HTTP context, since it works on " +
"session scope.");
}
catch (IllegalStateException isExc) {
// NOP; session was invalidated and will be removed anyway
}
}

}


<x-tad-smaller>Met vriendelijke groeten,

Jan Dockx
</x-tad-smaller><x-tad-smaller>
PeopleWare NV - Head Office</x-tad-smaller>
<x-tad-smaller>
Cdt.Weynsstraat 85
B-2660 Hoboken
Tel: +32 3 448.33.38
Fax: +32 3 448.32.66 </x-tad-smaller>
<x-tad-bigger>
</x-tad-bigger>
<x-tad-smaller>
PeopleWare NV - Branch Office Geel</x-tad-smaller>
<x-tad-smaller>
Kleinhoefstraat 5
B-2440 Geel
Tel: +32 14 57.00.90
Fax: +32 14 58.13.25</x-tad-smaller>
<x-tad-bigger>
</x-tad-bigger>
<x-tad-smaller>
http://www.peopleware.be/
</x-tad-smaller><x-tad-smaller>http://www.mobileware.be/</x-tad-smaller>

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to