[webbeans-commits] Webbeans SVN: r2660 - ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation.
webbeans-commits at lists.jboss.org
webbeans-commits at lists.jboss.org
Thu May 7 05:45:15 EDT 2009
Author: nickarls
Date: 2009-05-07 05:45:15 -0400 (Thu, 07 May 2009)
New Revision: 2660
Added:
ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/AbstractConversationManager.java
Modified:
ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ConversationEntry.java
ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ServletConversationManager.java
Log:
Split out an abstract conversation manager
Added: ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/AbstractConversationManager.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/AbstractConversationManager.java (rev 0)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/AbstractConversationManager.java 2009-05-07 09:45:15 UTC (rev 2660)
@@ -0,0 +1,246 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Use is subject to license terms.
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * 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.
+ */
+package org.jboss.webbeans.conversation;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+
+import javax.context.Conversation;
+import javax.inject.Current;
+
+import org.jboss.webbeans.context.ConversationContext;
+import org.jboss.webbeans.context.api.BeanStore;
+import org.jboss.webbeans.log.LogProvider;
+import org.jboss.webbeans.log.Logging;
+
+/**
+ * An abstract conversation manager
+ *
+ * @author Nicklas Karlsson
+ *
+ */
+public abstract class AbstractConversationManager implements ConversationManager
+{
+ private static LogProvider log = Logging.getLogProvider(AbstractConversationManager.class);
+
+ // The conversation terminator
+ @Current
+ private ConversationTerminator conversationTerminator;
+
+ // The current conversation
+ @Current
+ private ConversationImpl currentConversation;
+
+ // The conversation timeout in milliseconds waiting for access to a blocked
+ // conversation
+ @ConversationConcurrentAccessTimeout
+ private long concurrentAccessTimeout;
+
+ // A map of current active long-running conversation entries
+ private Map<String, ConversationEntry> longRunningConversations;
+
+ /**
+ * Creates a new conversation manager
+ */
+ public AbstractConversationManager()
+ {
+ log.trace("Created " + getClass());
+ longRunningConversations = new ConcurrentHashMap<String, ConversationEntry>();
+ }
+
+ public void beginOrRestoreConversation(String cid)
+ {
+ if (cid == null)
+ {
+ // No incoming conversation ID, nothing to do here, continue with
+ // a transient conversation
+ log.trace("No conversation id to restore");
+ return;
+ }
+ if (!longRunningConversations.containsKey(cid))
+ {
+ // We got an incoming conversation ID but it was not in the map of
+ // known ones, nothing to do. Log and return to continue with a
+ // transient conversation
+ log.warn("Could not restore long-running conversation " + cid);
+ return;
+ }
+ ConversationEntry resumedConversationEntry = longRunningConversations.get(cid);
+ // Try to get a lock to the requested conversation, log and return to
+ // continue with a transient conversation if we fail
+ try
+ {
+ if (!resumedConversationEntry.lock(concurrentAccessTimeout))
+ {
+ return;
+ }
+ }
+ catch (InterruptedException e)
+ {
+ log.debug("Interrupted while trying to acquire lock");
+ return;
+ }
+ // If we can't cancel the termination, release the lock, return and
+ // continue
+ // with a transient conversation
+ if (!resumedConversationEntry.cancelTermination())
+ {
+ resumedConversationEntry.unlock();
+ }
+ else
+ {
+ // If all goes well, set the identity of the current conversation to
+ // match the fetched long-running one
+ String oldConversation = currentConversation.toString();
+ currentConversation.switchTo(resumedConversationEntry.getConversation());
+ log.trace("Conversation switched from " + oldConversation + " to " + currentConversation);
+ }
+ }
+
+ // TODO: check that stuff gets terminated when you flip between several
+ // long-running conversations
+ public void cleanupConversation()
+ {
+ log.trace("Cleaning up conversation for " + currentConversation);
+ String cid = currentConversation.getId();
+ if (currentConversation.isLongRunning())
+ {
+ Future<?> terminationHandle = scheduleForTermination(cid, currentConversation.getTimeout());
+ // When the conversation ends, a long-running conversation needs to
+ // start its self-destruct. We can have the case where the conversation
+ // is a previously known conversation (that had it's termination
+ // canceled in the
+ // beginConversation) or the case where we have a completely new
+ // long-running conversation.
+ ConversationEntry longRunningConversation = longRunningConversations.get(cid);
+ if (longRunningConversation != null)
+ {
+ longRunningConversation.unlock();
+ longRunningConversation.reScheduleTermination(terminationHandle);
+ }
+ else
+ {
+ ConversationEntry conversationEntry = ConversationEntry.of(getBeanStore(cid), currentConversation, terminationHandle);
+ longRunningConversations.put(cid, conversationEntry);
+ }
+ log.trace("Scheduled " + currentConversation + " for termination, there are now " + longRunningConversations.size() + " long-running conversations");
+ }
+ else
+ {
+ // If the conversation is not long-running it can be a transient
+ // conversation that has been so from the start or it can be a
+ // long-running conversation that has been demoted during the request
+ log.trace("Destroying transient conversation " + currentConversation);
+ ConversationEntry longRunningConversation = longRunningConversations.remove(cid);
+ if (longRunningConversation != null)
+ {
+ longRunningConversation.cancelTermination();
+ longRunningConversation.unlock();
+ }
+ ConversationContext.instance().destroy();
+ }
+ // If the conversation has been switched from one long
+ // running-conversation to another with
+ // Conversation.begin(String), we need to unlock the original conversation
+ // and re-schedule
+ // it for termination
+ String originalCid = currentConversation.getOriginalCid();
+ ConversationEntry longRunningConversation = originalCid == null ? null : longRunningConversations.get(originalCid);
+ if (longRunningConversation != null)
+ {
+ longRunningConversation.unlock();
+ longRunningConversation.reScheduleTermination(scheduleForTermination(originalCid, currentConversation.getTimeout()));
+ }
+ }
+
+ /**
+ * Creates a termination task for and schedules it
+ *
+ * @param cid The id of the conversation to terminate
+ * @return The asynchronous job handle
+ */
+ private Future<?> scheduleForTermination(String cid, long timeout)
+ {
+ Runnable terminationTask = new TerminationTask(cid);
+ return conversationTerminator.scheduleForTermination(terminationTask, timeout);
+ }
+
+ /**
+ * A termination task that destroys the conversation entry
+ *
+ * @author Nicklas Karlsson
+ *
+ */
+ private class TerminationTask implements Runnable
+ {
+ // The conversation ID to terminate
+ private String cid;
+
+ /**
+ * Creates a new termination task
+ *
+ * @param cid The conversation ID
+ */
+ public TerminationTask(String cid)
+ {
+ this.cid = cid;
+ }
+
+ /**
+ * Executes the termination
+ */
+ public void run()
+ {
+ log.debug("Conversation " + cid + " timed out. Destroying it");
+ longRunningConversations.remove(cid).destroy();
+ log.trace("There are now " + longRunningConversations.size() + " long-running conversations");
+ }
+ }
+
+ public void destroyAllConversations()
+ {
+ log.debug("Destroying " + longRunningConversations.size() + " long-running conversations");
+ for (ConversationEntry conversationEntry : longRunningConversations.values())
+ {
+ conversationEntry.destroy();
+ }
+ longRunningConversations.clear();
+ }
+
+ public Set<Conversation> getLongRunningConversations()
+ {
+ Set<Conversation> conversations = new HashSet<Conversation>();
+ for (ConversationEntry conversationEntry : longRunningConversations.values())
+ {
+ conversations.add(conversationEntry.getConversation());
+ }
+ return Collections.unmodifiableSet(conversations);
+ }
+
+ public abstract BeanStore getBeanStore(String cid);
+
+}
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ConversationEntry.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ConversationEntry.java 2009-05-06 19:50:43 UTC (rev 2659)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ConversationEntry.java 2009-05-07 09:45:15 UTC (rev 2660)
@@ -21,12 +21,11 @@
import java.util.concurrent.locks.ReentrantLock;
import javax.context.Conversation;
-import javax.servlet.http.HttpSession;
import org.jboss.webbeans.context.ConversationContext;
+import org.jboss.webbeans.context.api.BeanStore;
import org.jboss.webbeans.log.LogProvider;
import org.jboss.webbeans.log.Logging;
-import org.jboss.webbeans.servlet.ConversationBeanStore;
/**
* Represents a long-running conversation entry
@@ -43,6 +42,8 @@
private Future<?> terminationHandle;
// The lock for concurrent access prevention
private ReentrantLock concurrencyLock;
+ // The Bean Store of the conversations
+ private BeanStore beanStore;
/**
* Creates a new conversation entry
@@ -50,8 +51,9 @@
* @param cid The conversation ID
* @param terminationHandle The timeout termination handle
*/
- protected ConversationEntry(Conversation conversation, Future<?> terminationHandle)
+ protected ConversationEntry(BeanStore beanStore, Conversation conversation, Future<?> terminationHandle)
{
+ this.beanStore = beanStore;
// conversation is a proxy so we need to make a "real" instance
this.conversation = new ConversationImpl(conversation);
this.terminationHandle = terminationHandle;
@@ -66,9 +68,9 @@
* @param terminationHandle The timeout termination handle
* @return A new conversation entry
*/
- public static ConversationEntry of(Conversation conversation, Future<?> terminationHandle)
+ public static ConversationEntry of(BeanStore beanStore, Conversation conversation, Future<?> terminationHandle)
{
- return new ConversationEntry(conversation, terminationHandle);
+ return new ConversationEntry(beanStore, conversation, terminationHandle);
}
/**
@@ -96,10 +98,8 @@
/**
* Destroys the conversation and it's associated conversational context
- *
- * @param session The HTTP session for the backing context bean store
*/
- public void destroy(HttpSession session)
+ public void destroy()
{
log.debug("Destroying conversation " + conversation);
if (!terminationHandle.isCancelled())
@@ -107,7 +107,7 @@
cancelTermination();
}
ConversationContext terminationContext = new ConversationContext();
- terminationContext.setBeanStore(new ConversationBeanStore(session, conversation.getId()));
+ terminationContext.setBeanStore(beanStore);
terminationContext.destroy();
log.trace("Conversation " + conversation + " destroyed");
}
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ServletConversationManager.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ServletConversationManager.java 2009-05-06 19:50:43 UTC (rev 2659)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/conversation/ServletConversationManager.java 2009-05-07 09:45:15 UTC (rev 2660)
@@ -23,37 +23,30 @@
package org.jboss.webbeans.conversation;
import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Future;
-import javax.context.Conversation;
import javax.context.SessionScoped;
-import javax.inject.Current;
import javax.inject.Produces;
import javax.servlet.http.HttpSession;
import org.jboss.webbeans.CurrentManager;
import org.jboss.webbeans.WebBean;
-import org.jboss.webbeans.context.ConversationContext;
+import org.jboss.webbeans.context.api.BeanStore;
import org.jboss.webbeans.log.LogProvider;
import org.jboss.webbeans.log.Logging;
+import org.jboss.webbeans.servlet.ConversationBeanStore;
import org.jboss.webbeans.servlet.HttpSessionManager;
/**
- * The default conversation manager
+ * The HTTP session based conversation manager
*
* @author Nicklas Karlsson
*
*/
@SessionScoped
@WebBean
-public class ServletConversationManager implements ConversationManager, Serializable
+public class ServletConversationManager extends AbstractConversationManager implements Serializable
{
- private static final long serialVersionUID = 889078932817674680L;
+ private static final long serialVersionUID = 1647848566880659085L;
private static LogProvider log = Logging.getLogProvider(ServletConversationManager.class);
@@ -61,31 +54,13 @@
private static final long CONVERSATION_CONCURRENT_ACCESS_TIMEOUT_IN_MS = 1 * 1000;
private static final String CONVERSATION_ID_NAME = "cid";
- // The conversation terminator
- @Current
- private ConversationTerminator conversationTerminator;
-
- // The current conversation
- @Current
- private ConversationImpl currentConversation;
-
- // The conversation timeout in milliseconds waiting for access to a blocked
- // conversation
- @ConversationConcurrentAccessTimeout
- private long concurrentAccessTimeout;
-
- // A map of current active long-running conversation entries
- private Map<String, ConversationEntry> longRunningConversations;
-
- /**
- * Creates a new conversation manager
- */
- public ServletConversationManager()
+ @Override
+ public BeanStore getBeanStore(String cid)
{
- log.trace("Created " + getClass());
- longRunningConversations = new ConcurrentHashMap<String, ConversationEntry>();
+ HttpSession session = CurrentManager.rootManager().getInstanceByType(HttpSessionManager.class).getSession();
+ return new ConversationBeanStore(session, cid);
}
-
+
@Produces
@ConversationInactivityTimeout
@WebBean
@@ -112,178 +87,5 @@
log.trace("Produced conversation id name " + CONVERSATION_ID_NAME);
return CONVERSATION_ID_NAME;
}
-
- public void beginOrRestoreConversation(String cid)
- {
- if (cid == null)
- {
- // No incoming conversation ID, nothing to do here, continue with
- // a transient conversation
- log.trace("No conversation id to restore");
- return;
- }
- if (!longRunningConversations.containsKey(cid))
- {
- // We got an incoming conversation ID but it was not in the map of
- // known ones, nothing to do. Log and return to continue with a
- // transient conversation
- log.warn("Could not restore long-running conversation " + cid);
- return;
- }
- ConversationEntry resumedConversationEntry = longRunningConversations.get(cid);
- // Try to get a lock to the requested conversation, log and return to
- // continue with a transient conversation if we fail
- try
- {
- if (!resumedConversationEntry.lock(concurrentAccessTimeout))
- {
- return;
- }
- }
- catch (InterruptedException e)
- {
- log.debug("Interrupted while trying to acquire lock");
- return;
- }
- // If we can't cancel the termination, release the lock, return and
- // continue
- // with a transient conversation
- if (!resumedConversationEntry.cancelTermination())
- {
- resumedConversationEntry.unlock();
- }
- else
- {
- // If all goes well, set the identity of the current conversation to
- // match the fetched long-running one
- String oldConversation = currentConversation.toString();
- currentConversation.switchTo(resumedConversationEntry.getConversation());
- log.trace("Conversation switched from " + oldConversation + " to " + currentConversation);
- }
- }
-
- // TODO: check that stuff gets terminated when you flip between several
- // long-running conversations
- public void cleanupConversation()
- {
- log.trace("Cleaning up conversation for " + currentConversation);
- String cid = currentConversation.getId();
- if (currentConversation.isLongRunning())
- {
- Future<?> terminationHandle = scheduleForTermination(cid, currentConversation.getTimeout());
- // When the conversation ends, a long-running conversation needs to
- // start its self-destruct. We can have the case where the conversation
- // is a previously known conversation (that had it's termination
- // canceled in the
- // beginConversation) or the case where we have a completely new
- // long-running conversation.
- ConversationEntry longRunningConversation = longRunningConversations.get(cid);
- if (longRunningConversation != null)
- {
- longRunningConversation.unlock();
- longRunningConversation.reScheduleTermination(terminationHandle);
- }
- else
- {
- ConversationEntry conversationEntry = ConversationEntry.of(currentConversation, terminationHandle);
- longRunningConversations.put(cid, conversationEntry);
- }
- log.trace("Scheduled " + currentConversation + " for termination, there are now " + longRunningConversations.size() + " long-running conversations");
- }
- else
- {
- // If the conversation is not long-running it can be a transient
- // conversation that has been so from the start or it can be a
- // long-running conversation that has been demoted during the request
- log.trace("Destroying transient conversation " + currentConversation);
- ConversationEntry longRunningConversation = longRunningConversations.remove(cid);
- if (longRunningConversation != null)
- {
- longRunningConversation.cancelTermination();
- longRunningConversation.unlock();
- }
- ConversationContext.instance().destroy();
- }
- // If the conversation has been switched from one long
- // running-conversation to another with
- // Conversation.begin(String), we need to unlock the original conversation
- // and re-schedule
- // it for termination
- String originalCid = currentConversation.getOriginalCid();
- ConversationEntry longRunningConversation = originalCid == null ? null : longRunningConversations.get(originalCid);
- if (longRunningConversation != null)
- {
- longRunningConversation.unlock();
- longRunningConversation.reScheduleTermination(scheduleForTermination(originalCid, currentConversation.getTimeout()));
- }
- }
-
- /**
- * Creates a termination task for and schedules it
- *
- * @param cid The id of the conversation to terminate
- * @return The asynchronous job handle
- */
- private Future<?> scheduleForTermination(String cid, long timeout)
- {
- HttpSession session = CurrentManager.rootManager().getInstanceByType(HttpSessionManager.class).getSession();
- Runnable terminationTask = new TerminationTask(cid, session);
- return conversationTerminator.scheduleForTermination(terminationTask, timeout);
- }
-
- /**
- * A termination task that destroys the conversation entry
- *
- * @author Nicklas Karlsson
- *
- */
- private class TerminationTask implements Runnable
- {
- // The conversation ID to terminate
- private String cid;
- private HttpSession session;
-
- /**
- * Creates a new termination task
- *
- * @param cid The conversation ID
- */
- public TerminationTask(String cid, HttpSession session)
- {
- this.cid = cid;
- this.session = session;
- }
-
- /**
- * Executes the termination
- */
- public void run()
- {
- log.debug("Conversation " + cid + " timed out. Destroying it");
- longRunningConversations.remove(cid).destroy(session);
- log.trace("There are now " + longRunningConversations.size() + " long-running conversations");
- }
- }
-
- public void destroyAllConversations()
- {
- HttpSession session = CurrentManager.rootManager().getInstanceByType(HttpSessionManager.class).getSession();
- log.debug("Destroying " + longRunningConversations.size() + " long-running conversations in session " + session.getId());
- for (ConversationEntry conversationEntry : longRunningConversations.values())
- {
- conversationEntry.destroy(session);
- }
- longRunningConversations.clear();
- }
-
- public Set<Conversation> getLongRunningConversations()
- {
- Set<Conversation> conversations = new HashSet<Conversation>();
- for (ConversationEntry conversationEntry : longRunningConversations.values())
- {
- conversations.add(conversationEntry.getConversation());
- }
- return Collections.unmodifiableSet(conversations);
- }
-
+
}
More information about the weld-commits
mailing list