[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