You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by im...@apache.org on 2007/08/30 14:28:17 UTC

svn commit: r571134 - in /myfaces/orchestra/trunk: core/src/main/java/org/apache/myfaces/orchestra/conversation/ core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ cor...

Author: imario
Date: Thu Aug 30 05:28:16 2007
New Revision: 571134

URL: http://svn.apache.org/viewvc?rev=571134&view=rev
Log:
moved from the "wiper-thread-per-session" concept to a single-wiper-thread way.
changed timeout handling for the conversation, now, the timeout handling is just an aspect on the conversation which can be configured through the ConversationPolicy

Added:
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java   (with props)
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java   (with props)
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java   (with props)
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java   (with props)
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java   (with props)
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/FlashScopePhaseListener.java
      - copied, changed from r571058, myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java   (with props)
Modified:
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/ConversationPolicy.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringConversationScope.java
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringFlashScope.java
    myfaces/orchestra/trunk/core/src/main/resources/META-INF/faces-config.xml
    myfaces/orchestra/trunk/examples/src/main/webapp/WEB-INF/web.xml

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/Conversation.java Thu Aug 30 05:28:16 2007
@@ -60,6 +60,8 @@
 
 	private final ConversationContext conversationContext;
 
+	private ConversationAspects conversationAspects = new ConversationAspects();
+
 	private boolean invalid = false;
 	private boolean queueInvalid = false;
 
@@ -280,7 +282,7 @@
 
 	/**
 	 * Get the current conversation.
-	 * 
+	 *
 	 * @return The conversation object associated with the nearest object in the call-stack that
 	 * is configured to be in a conversation. Null is returned when no object in the call-stack
 	 * is in a conversation.
@@ -309,7 +311,7 @@
 	}
 
 	/**
-	 * Returns the info about the current conversation 
+	 * Returns the info about the current conversation
 	 */
 	static CurrentConversationInfo getCurrentInstanceInfo()
 	{
@@ -324,8 +326,8 @@
 	}
 
 	/**
-	 * Increase one to the "conversation active" counter. 
-	 * 
+	 * Increase one to the "conversation active" counter.
+	 *
 	 * This is called when a method is invoked on a bean that is within this conversation.
 	 * When the method returns, leaveConversation is invoked. The result is that the count
 	 * is greater than zero whenever there is a bean belonging to this conversation on
@@ -359,5 +361,19 @@
 		{
 			return activeCount > 0;
 		}
+	}
+
+	ConversationAspects getAspects()
+	{
+		return conversationAspects;
+	}
+
+	/**
+	 * get the aspect corresponding to the given class.
+	 * @return null if such an apsect has not been attached to this conversation
+	 */
+	public ConversationAspect getAspect(Class conversationAspectClass)
+	{
+		return conversationAspects.getAspect(conversationAspectClass);
 	}
 }

Added: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java?rev=571134&view=auto
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java (added)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java Thu Aug 30 05:28:16 2007
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.orchestra.conversation;
+
+/**
+ * <p>
+ * A conversation aspect which can be attached to an conversation.
+ * </p>
+ * <p>
+ * Orchestra uses this thing to
+ * <ul>
+ *     <li>Check the timeout of a conversation</li>
+ *     <li>Connect the conversation to the FlashScopeManager</li>
+ * </ul>
+ * </p>
+ */
+public abstract class ConversationAspect
+{
+	private final Conversation conversation;
+
+	public ConversationAspect(Conversation conversation)
+	{
+		this.conversation = conversation;
+	}
+
+	public Conversation getConversation()
+	{
+		return conversation;
+	}
+}

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspect.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java?rev=571134&view=auto
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java (added)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java Thu Aug 30 05:28:16 2007
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.orchestra.conversation;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * Maintains a list of aspects the system might attach to a conversation instance.
+ * </p>
+ * <p>
+ * An aspect can be:
+ * <ul>
+ *     <li>Timeout handling</li>
+ *     <li>Flash Scope handling</li>
+ * </ul>
+ * </p>
+ */
+public class ConversationAspects
+{
+	private Map conversationAspects = new HashMap();
+
+	public void addAspect(ConversationAspect aspect)
+	{
+		conversationAspects.put(aspect.getClass().getName(), aspect);
+	}
+
+	public ConversationAspect getAspect(Class aspectClass)
+	{
+		return (ConversationAspect) conversationAspects.get(aspectClass.getName());
+	}
+}

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationAspects.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationContext.java Thu Aug 30 05:28:16 2007
@@ -22,11 +22,13 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.myfaces.orchestra.conversation.spring.ConversationPolicy;
+import org.apache.myfaces.orchestra.lib.OrchestraException;
 
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.TreeMap;
-import java.util.Iterator;
-import java.util.Arrays;
 
 /**
  * <p>The ConversationContext handles all conversations within the current context</p>
@@ -40,16 +42,20 @@
 	private final Log log = LogFactory.getLog(ConversationContext.class);
 
 	private final long id;
+	private final ConversationManager conversationManager;
 
 	private final Map attributes = new TreeMap();
 
 	private final Map conversations = new TreeMap();
 
 	private long lastAccess;
+	private long timeout = 30 * 60 * 1000;
 
-	protected ConversationContext(long id)
+	protected ConversationContext(ConversationManager conversationManager, long id)
 	{
 		this.id = id;
+		this.conversationManager = conversationManager;
+
 		touch();
 	}
 
@@ -75,6 +81,26 @@
 	}
 
 	/**
+	 * Get the timeout after which this context will be closed.
+	 *
+	 * @see #setTimeout
+	 */
+	public long getTimeout()
+	{
+		return timeout;
+	}
+
+	/**
+	 * Set the timeout after which this context will be closed.
+	 * <br />
+	 * A value of -1 means no timeout checking.
+	 */
+	public void setTimeout(long timeout)
+	{
+		this.timeout = timeout;
+	}
+
+	/**
 	 * <p>Invalidate all conversations within this context</p>
 	 */
 	protected void clear()
@@ -105,13 +131,56 @@
 			Conversation conversation = (Conversation) conversations.get(name);
 			if (conversation == null)
 			{
-				conversation = new Conversation(this, name, policy);
+				conversation = createConversation(name, policy);
+
 				conversations.put(name, conversation);
 			}
 			return conversation;
 		}
 	}
 
+	protected Conversation createConversation(String name, ConversationPolicy policy)
+	{
+		Conversation conversation;
+		conversation = new Conversation(this, name, policy);
+
+		Class[] aspectClasses = policy.getConversationAspects();
+		if (aspectClasses != null)
+		{
+			for (int i = 0; i<aspectClasses.length; i++)
+			{
+				Class aspectClass = aspectClasses[i];
+				ConversationAspect aspect;
+				try
+				{
+					aspect = (ConversationAspect) aspectClass.getConstructor(new Class[]
+					{
+						Conversation.class
+					}).newInstance(conversation);
+				}
+				catch (InstantiationException e)
+				{
+					throw new OrchestraException(e);
+				}
+				catch (IllegalAccessException e)
+				{
+					throw new OrchestraException(e);
+				}
+				catch (InvocationTargetException e)
+				{
+					throw new OrchestraException(e);
+				}
+				catch (NoSuchMethodException e)
+				{
+					throw new OrchestraException(e);
+				}
+
+				conversation.getAspects().addAspect(aspect);
+			}
+		}
+		return conversation;
+	}
+
 	/**
 	 * <p>remove the conversation from this context.</p>
 	 * <p>Notice: Its assumed that the conversation has already been invalidated</p>
@@ -208,9 +277,6 @@
 	{
 		synchronized (this)
 		{
-			long timeToLive = 30 * 60 * 1000;
-			long checkTime = System.currentTimeMillis();
-
 			Conversation[] convArray = new Conversation[conversations.size()];
 			conversations.values().toArray(convArray);
 
@@ -218,7 +284,11 @@
 			{
 				Conversation conversation = convArray[i];
 
-				if (conversation.getLastAccess() + timeToLive < checkTime)
+				ConversationTimeoutableAspect timeoutAspect =
+					(ConversationTimeoutableAspect)
+						conversation.getAspect(ConversationTimeoutableAspect.class);
+
+				if (timeoutAspect.isTimeoutReached())
 				{
 					if (log.isDebugEnabled())
 					{

Added: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java?rev=571134&view=auto
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java (added)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java Thu Aug 30 05:28:16 2007
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.orchestra.conversation;
+
+/**
+ * Connect the conversation to the FlashScopeManager
+ */
+public class ConversationFlashScopeAspect extends ConversationAspect
+{
+	public ConversationFlashScopeAspect(Conversation conversation)
+	{
+		super(conversation);
+	}
+
+	public void markAsAccessed()
+	{
+		FlashScopeManager.getInstance().addConversationAccess(getConversation().getName());
+	}
+
+	public boolean isAccessed()
+	{
+		return FlashScopeManager.getInstance().isConversationAccessed(getConversation().getName());
+	}
+}

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationFlashScopeAspect.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationManager.java Thu Aug 30 05:28:16 2007
@@ -62,39 +62,8 @@
 
 	// private Set managedScopes;
 
-	private class ConversationWiperThread extends Thread
-	{
-		private final static long CHECK_TIME = 5 * 60 * 1000; // every 5 min
-
-		public ConversationWiperThread()
-		{
-			setDaemon(true);
-			setName(ConversationWiperThread.class.getName());
-		}
-
-		public void run()
-		{
-			while (!isInterrupted())
-			{
-				checkTimeouts();
-
-				try
-				{
-					Thread.sleep(CHECK_TIME);
-				}
-				catch (InterruptedException e)
-				{
-					log.warn(e.getLocalizedMessage(), e);
-				}
-			}
-		}
-	}
-
-	private ConversationWiperThread wiperThread = new ConversationWiperThread();
-
 	protected ConversationManager()
 	{
-		wiperThread.start();
 	}
 
 	/**
@@ -198,7 +167,7 @@
 			ConversationContext conversationContext = (ConversationContext) conversationContexts.get(conversationContextId);
 			if (conversationContext == null)
 			{
-				conversationContext = new ConversationContext(conversationContextId.longValue());
+				conversationContext = new ConversationContext(this, conversationContextId.longValue());
 				conversationContexts.put(conversationContextId, conversationContext);
 			}
 
@@ -386,7 +355,6 @@
 			conversationContexts.entrySet().toArray(contexts);
 		}
 
-		long timeToLive = 30 * 60 * 1000;
 		long checkTime = System.currentTimeMillis();
 
 		for (int i = 0; i<contexts.length; i++)
@@ -397,7 +365,9 @@
 			ConversationContext conversationContext = (ConversationContext) context.getValue();
 			conversationContext.checkConversationTimeout();
 
-			if (conversationContext.getLastAccess() + timeToLive < checkTime)
+			if (conversationContext.getTimeout() > -1 &&
+				(conversationContext.getLastAccess() +
+				conversationContext.getTimeout()) < checkTime)
 			{
 				if (log.isDebugEnabled())
 				{

Added: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java?rev=571134&view=auto
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java (added)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java Thu Aug 30 05:28:16 2007
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.orchestra.conversation;
+
+/**
+ */
+public class ConversationTimeoutableAspect extends ConversationAspect
+{
+	private long timeout = 30 * 60 * 1000;
+
+	public ConversationTimeoutableAspect(Conversation conversation)
+	{
+		super(conversation);
+	}
+
+	/**
+	 * Get the timeout ins ms after which this conversatino will be invalidated.
+	 *
+	 * @see #setTimeout
+	 */
+	public long getTimeout()
+	{
+		return timeout;
+	}
+
+	/**
+	 * Set the timeout in ms after which this conversatino will be invalidated.
+	 * <br />
+	 * A value of -1 means no timeout checking
+	 */
+	public void setTimeout(long timeout)
+	{
+		this.timeout = timeout;
+	}
+
+	/**
+	 * check if this conversation reached the timeout period
+	 */
+	public boolean isTimeoutReached()
+	{
+		return getTimeout() > -1 && (getConversation().getLastAccess() + getTimeout() < System.currentTimeMillis());
+	}
+}

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationTimeoutableAspect.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java?rev=571134&view=auto
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java (added)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java Thu Aug 30 05:28:16 2007
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.orchestra.conversation;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The ConversationWiperThread will trigger the conversation timeout check
+ */
+public class ConversationWiperThread extends Thread
+{
+	private final Log log = LogFactory.getLog(ConversationWiperThread.class);
+
+	private final long checkTime;
+
+	private Map conversationManagers = new HashMap();
+
+	public ConversationWiperThread(long checkTime)
+	{
+		this.checkTime = checkTime;
+
+		setDaemon(true);
+		setName(ConversationWiperThread.class.getName());
+	}
+
+	/**
+	 * This will add a ConversationManager to check. If there is already a ConversationManager associated
+	 * to the given <code>id</code>, the old ConversationManager will be replaces.
+	 */
+	public void addConversationManager(String id, ConversationManager conversationManager)
+	{
+		synchronized (conversationManagers)
+		{
+			conversationManagers.put(id, conversationManager);
+		}
+	}
+
+	/**
+	 * Remove a ConversationManager from the list to check.
+	 */
+	public void removeConversationManager(String id)
+	{
+		synchronized (conversationManagers)
+		{
+			conversationManagers.remove(id);
+		}
+	}
+
+	public void run()
+	{
+		if (log.isDebugEnabled())
+		{
+			log.debug("ConversationWiperThread startup"); // NON-NLS
+		}
+		_run();
+		if (log.isInfoEnabled())
+		{
+			log.debug("ConversationWiperThread shtudown"); // NON-NLS
+		}
+	}
+
+	private void _run()
+	{
+		while (!isInterrupted())
+		{
+			ConversationManager[] managersArray;
+			synchronized (conversationManagers)
+			{
+				managersArray = new ConversationManager[conversationManagers.size()];
+				conversationManagers.values().toArray(managersArray);
+			}
+
+			for (int i = 0; i<managersArray.length; i++)
+			{
+				ConversationManager conversationManager = managersArray[i];
+				conversationManager.checkTimeouts();
+			}
+
+			try
+			{
+				Thread.sleep(checkTime);
+			}
+			catch (InterruptedException e)
+			{
+				return;
+			}
+		}
+	}
+}

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/ConversationWiperThread.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java Thu Aug 30 05:28:16 2007
@@ -19,82 +19,27 @@
 
 package org.apache.myfaces.orchestra.conversation.jsf;
 
-import org.apache.myfaces.orchestra.conversation.Conversation;
 import org.apache.myfaces.orchestra.conversation.ConversationManager;
-import org.apache.myfaces.orchestra.conversation.FlashScopeManager;
-import org.apache.myfaces.orchestra.conversation.spring.ConversationPolicy;
 
 import javax.faces.event.PhaseEvent;
 import javax.faces.event.PhaseId;
 import javax.faces.event.PhaseListener;
-import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 
 /**
- * Ensure that Orchestra is initialised for the current user, and handle Flash conversations.
+ * Ensure that Orchestra is initialised for the current user.
  * <p>
  * At start of request processing, if this is a new http session then initialise Orchestra
  * for this session.
- * <p>
- * At the end of request processing, delete any flash-scope conversations for which no
- * bean in that scope has been accessed during the request.
  */
 public class ConversationPhaseListener implements PhaseListener
 {
+	private static final long serialVersionUID = 1L;
+
 	private final static String SYSTEM_INITIALIZED = ConversationPhaseListener.class.getName() + ".INITIALIZED";
 
 	public void afterPhase(PhaseEvent event)
 	{
-		if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
-		{
-			invalidateFlashConversations(event.getFacesContext().getViewRoot().getViewId());
-		}
-	}
-
-	/**
-	 * invalidates any conversation with policy {@link org.apache.myfaces.orchestra.conversation.spring.ConversationPolicy#FLASH}
-	 * not accessed during a http request
-	 * @param viewId
-	 */
-	protected void invalidateFlashConversations(String viewId)
-	{
-		FlashScopeManager flashManager = FlashScopeManager.getInstance();
-		if (flashManager.isIgnoreRequest())
-		{
-			return;
-		}
-
-		if (flashManager.getFlashScopeManagerConfiguration() != null)
-		{
-			Set ignoredViewIds = flashManager.getFlashScopeManagerConfiguration().getIgnoreViewIds();
-			if (ignoredViewIds != null && ignoredViewIds.contains(viewId))
-			{
-				return;
-			}
-		}
-
-		ConversationManager conversationManager = ConversationManager.getInstance();
-		if (conversationManager == null)
-		{
-			return;
-		}
-
-		Iterator iterConversations = conversationManager.iterateConversations();
-		if (iterConversations == null || !iterConversations.hasNext())
-		{
-			return;
-		}
-
-		while (iterConversations.hasNext())
-		{
-			Conversation conversation = (Conversation) iterConversations.next();
-			if (ConversationPolicy.FLASH.equals(conversation.getPolicy()) &&
-				!flashManager.isConversationAccessed(conversation.getName()))
-			{
-				conversation.invalidate();
-			}
-		}
 	}
 
 	public void beforePhase(PhaseEvent event)
@@ -122,6 +67,6 @@
 
 	public PhaseId getPhaseId()
 	{
-		return PhaseId.ANY_PHASE;
+		return PhaseId.RESTORE_VIEW;
 	}
 }

Copied: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/FlashScopePhaseListener.java (from r571058, myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java)
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/FlashScopePhaseListener.java?p2=myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/FlashScopePhaseListener.java&p1=myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java&r1=571058&r2=571134&rev=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/ConversationPhaseListener.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/jsf/FlashScopePhaseListener.java Thu Aug 30 05:28:16 2007
@@ -20,29 +20,25 @@
 package org.apache.myfaces.orchestra.conversation.jsf;
 
 import org.apache.myfaces.orchestra.conversation.Conversation;
+import org.apache.myfaces.orchestra.conversation.ConversationFlashScopeAspect;
 import org.apache.myfaces.orchestra.conversation.ConversationManager;
 import org.apache.myfaces.orchestra.conversation.FlashScopeManager;
-import org.apache.myfaces.orchestra.conversation.spring.ConversationPolicy;
 
 import javax.faces.event.PhaseEvent;
 import javax.faces.event.PhaseId;
 import javax.faces.event.PhaseListener;
 import java.util.Iterator;
-import java.util.Map;
 import java.util.Set;
 
 /**
- * Ensure that Orchestra is initialised for the current user, and handle Flash conversations.
- * <p>
- * At start of request processing, if this is a new http session then initialise Orchestra
- * for this session.
+ * Handle Flash conversations.
  * <p>
  * At the end of request processing, delete any flash-scope conversations for which no
  * bean in that scope has been accessed during the request.
  */
-public class ConversationPhaseListener implements PhaseListener
+public class FlashScopePhaseListener implements PhaseListener
 {
-	private final static String SYSTEM_INITIALIZED = ConversationPhaseListener.class.getName() + ".INITIALIZED";
+	private static final long serialVersionUID = 1L;
 
 	public void afterPhase(PhaseEvent event)
 	{
@@ -52,6 +48,10 @@
 		}
 	}
 
+	public void beforePhase(PhaseEvent event)
+	{
+	}
+
 	/**
 	 * invalidates any conversation with policy {@link org.apache.myfaces.orchestra.conversation.spring.ConversationPolicy#FLASH}
 	 * not accessed during a http request
@@ -89,39 +89,19 @@
 		while (iterConversations.hasNext())
 		{
 			Conversation conversation = (Conversation) iterConversations.next();
-			if (ConversationPolicy.FLASH.equals(conversation.getPolicy()) &&
-				!flashManager.isConversationAccessed(conversation.getName()))
-			{
-				conversation.invalidate();
-			}
-		}
-	}
+			ConversationFlashScopeAspect aspect =
+				(ConversationFlashScopeAspect)
+					conversation.getAspect(ConversationFlashScopeAspect.class);
 
-	public void beforePhase(PhaseEvent event)
-	{
-		if (PhaseId.RESTORE_VIEW.equals(event.getPhaseId()))
-		{
-			initialize(event);
-		}
-	}
-
-	private void initialize(PhaseEvent event)
-	{
-		Map sessionMap = event.getFacesContext().getExternalContext().getSessionMap();
-		if (sessionMap != null)
-		{
-			if (!Boolean.TRUE.equals(sessionMap.get(SYSTEM_INITIALIZED)))
+			if (aspect != null && !aspect.isAccessed())
 			{
-				// ensure correct setup of system
-				ConversationManager.getInstance();
-
-				sessionMap.put(SYSTEM_INITIALIZED, Boolean.TRUE);
+				conversation.invalidate();
 			}
 		}
 	}
 
 	public PhaseId getPhaseId()
 	{
-		return PhaseId.ANY_PHASE;
+		return PhaseId.RENDER_RESPONSE;
 	}
-}
+}
\ No newline at end of file

Added: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java?rev=571134&view=auto
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java (added)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java Thu Aug 30 05:28:16 2007
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.orchestra.conversation.servlet;
+
+import org.apache.myfaces.orchestra.conversation.ConversationManager;
+import org.apache.myfaces.orchestra.conversation.ConversationWiperThread;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionListener;
+import javax.servlet.http.HttpSessionEvent;
+
+/**
+ * <p>
+ * This listener will maintain a single thread for all conversation managers active within the system.
+ * <br />
+ * See {@link org.apache.myfaces.orchestra.conversation.ConversationWiperThread} for more details.
+ * </p>
+ */
+public class ConversationManagerSessionListener
+	implements HttpSessionAttributeListener, ServletContextListener, HttpSessionListener
+{
+	private final static long DEFAULT_CHECK_TIME = 5 * 60 * 1000; // every 5 min
+
+	private final static String CHECK_TIME = "org.apache.myfaces.orchestra.WIPER_THREAD_CHECK_TIME"; // NON-NLS
+
+	private ConversationWiperThread conversationWiperThread;
+
+	public void contextInitialized(ServletContextEvent event)
+	{
+		long checkTime = DEFAULT_CHECK_TIME;
+		String checkTimeString = event.getServletContext().getInitParameter(CHECK_TIME);
+		if (checkTimeString != null)
+		{
+			checkTime = Long.parseLong(checkTimeString);
+		}
+
+		conversationWiperThread = new ConversationWiperThread(checkTime);
+		conversationWiperThread.start();
+	}
+
+	public void contextDestroyed(ServletContextEvent event)
+	{
+		conversationWiperThread.interrupt();
+		conversationWiperThread = null;
+	}
+
+	public void attributeAdded(HttpSessionBindingEvent event)
+	{
+		if (event.getValue() instanceof ConversationManager)
+		{
+			conversationWiperThread.addConversationManager(
+				event.getSession().getId(),
+				(ConversationManager) event.getValue());
+		}
+	}
+
+	public void attributeRemoved(HttpSessionBindingEvent event)
+	{
+		if (event.getValue() instanceof ConversationManager)
+		{
+			conversationWiperThread.removeConversationManager(event.getSession().getId());
+		}
+	}
+
+	public void attributeReplaced(HttpSessionBindingEvent event)
+	{
+		if (event.getValue() instanceof ConversationManager)
+		{
+			conversationWiperThread.addConversationManager(
+				event.getSession().getId(),
+				(ConversationManager) event.getValue());
+		}
+	}
+
+	public void sessionCreated(HttpSessionEvent event)
+	{
+	}
+
+	public void sessionDestroyed(HttpSessionEvent event)
+	{
+		// just in case we didn't get a attributeRemoved, remove any attached conversatoinManager for this session
+		conversationWiperThread.removeConversationManager(event.getSession().getId());
+	}
+}

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/servlet/ConversationManagerSessionListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/ConversationPolicy.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/ConversationPolicy.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/ConversationPolicy.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/ConversationPolicy.java Thu Aug 30 05:28:16 2007
@@ -18,19 +18,33 @@
  */
 package org.apache.myfaces.orchestra.conversation.spring;
 
+import org.apache.myfaces.orchestra.conversation.ConversationTimeoutableAspect;
+
 /**
  * configuration for the scope of the conversation
  */
 public class ConversationPolicy
 {
 	/**
-	 * a conversation with MANUAL policy will end when:
+	 * a conversation with AUTO policy will end when:
 	 * <ul>
 	 * <li>using the conversation API (e.g. {@link org.apache.myfaces.orchestra.conversation.Conversation#invalidate()}</li>
 	 * <li>reach a timeout</li>
 	 * </ul>
 	 */
-	public final static ConversationPolicy MANUAL = new ConversationPolicy("MANUAL");
+	public final static ConversationPolicy TIME = new ConversationPolicy(
+		"TIME",
+		new Class[]{ConversationTimeoutableAspect.class});
+
+	/**
+	 * a conversation with MANUAL policy will end when:
+	 * <ul>
+	 * <li>using the conversation API (e.g. {@link org.apache.myfaces.orchestra.conversation.Conversation#invalidate()}</li>
+	 * </ul>
+	 */
+	public final static ConversationPolicy MANUAL = new ConversationPolicy(
+		"MANUAL",
+		null);
 
 	/**
 	 * a conversation with FLASH policy will end when:
@@ -40,14 +54,18 @@
 	 * <li>reach a timeout</li>
 	 * </ul>
 	 */
-	public final static ConversationPolicy FLASH = new ConversationPolicy("FLASH");
+	public final static ConversationPolicy FLASH = new ConversationPolicy(
+		"FLASH",
+		new Class[]{ConversationTimeoutableAspect.class});
 
 
 	private final String name;
+	private final Class[] conversationAspects;
 
-	private ConversationPolicy(String name)
+	private ConversationPolicy(String name, Class[] conversationAspects)
 	{
 		this.name = name;
+		this.conversationAspects = conversationAspects;
 	}
 
 	public boolean equals(Object obj)
@@ -58,5 +76,10 @@
 		}
 
 		return false;
+	}
+
+	public Class[] getConversationAspects()
+	{
+		return conversationAspects;
 	}
 }

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringConversationScope.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringConversationScope.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringConversationScope.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringConversationScope.java Thu Aug 30 05:28:16 2007
@@ -43,7 +43,7 @@
 /**
  * Handles creation and lookup of any bean whose bean-definition specifies a scope
  * of "conversation".
- * 
+ *
  * <p>adapts the conversation scope to a new spring scope</p>
  * <p>It will also apply any advice configured</p>
  * <p>A sample configuration for a conversation scope with persistence
@@ -186,7 +186,7 @@
 
 	protected ConversationPolicy getConversationPolicy()
 	{
-		return ConversationPolicy.MANUAL;
+		return ConversationPolicy.TIME;
 	}
 
 	/**
@@ -301,8 +301,8 @@
 		);
 	}
 
-	/** 
-	 * Get an ApplicationContext injected by Spring. See ApplicationContextAware interface. 
+	/**
+	 * Get an ApplicationContext injected by Spring. See ApplicationContextAware interface.
 	 */
 	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
 	{

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringFlashScope.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringFlashScope.java?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringFlashScope.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/conversation/spring/SpringFlashScope.java Thu Aug 30 05:28:16 2007
@@ -20,7 +20,7 @@
 package org.apache.myfaces.orchestra.conversation.spring;
 
 import org.apache.myfaces.orchestra.conversation.Conversation;
-import org.apache.myfaces.orchestra.conversation.FlashScopeManager;
+import org.apache.myfaces.orchestra.conversation.ConversationFlashScopeAspect;
 
 /**
  * provides a flash scope, that is, a bean will be discarded as soon as it is no longer referenced
@@ -39,6 +39,11 @@
 
 	protected void notifyAccessConversation(Conversation conversation)
 	{
-		FlashScopeManager.getInstance().addConversationAccess(conversation.getName());
+		ConversationFlashScopeAspect flashScopeAspect =
+			(ConversationFlashScopeAspect) conversation.getAspect(ConversationFlashScopeAspect.class);
+		if (flashScopeAspect != null)
+		{
+			flashScopeAspect.markAsAccessed();
+		}
 	}
 }

Modified: myfaces/orchestra/trunk/core/src/main/resources/META-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/resources/META-INF/faces-config.xml?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/resources/META-INF/faces-config.xml (original)
+++ myfaces/orchestra/trunk/core/src/main/resources/META-INF/faces-config.xml Thu Aug 30 05:28:16 2007
@@ -36,6 +36,7 @@
 
 	<lifecycle>
 		<phase-listener>org.apache.myfaces.orchestra.conversation.jsf.ConversationPhaseListener</phase-listener>
+		<phase-listener>org.apache.myfaces.orchestra.conversation.jsf.FlashScopePhaseListener</phase-listener>
 		<phase-listener>org.apache.myfaces.orchestra.viewController.jsf.ViewControllerPhaseListener</phase-listener>
 	</lifecycle>
 

Modified: myfaces/orchestra/trunk/examples/src/main/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/examples/src/main/webapp/WEB-INF/web.xml?rev=571134&r1=571133&r2=571134&view=diff
==============================================================================
--- myfaces/orchestra/trunk/examples/src/main/webapp/WEB-INF/web.xml (original)
+++ myfaces/orchestra/trunk/examples/src/main/webapp/WEB-INF/web.xml Thu Aug 30 05:28:16 2007
@@ -34,6 +34,9 @@
 	<listener>
 		<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
 	</listener>
+	<listener>
+		<listener-class>org.apache.myfaces.orchestra.conversation.servlet.ConversationManagerSessionListener</listener-class>
+	</listener>
 
 	<context-param>
 		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>