You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by ge...@apache.org on 2010/01/31 22:33:50 UTC

svn commit: r905127 - in /openwebbeans/trunk: webbeans-impl/src/main/java/org/apache/webbeans/component/ webbeans-impl/src/main/java/org/apache/webbeans/conversation/ webbeans-jsf/src/main/java/org/apache/webbeans/jsf/

Author: gerdogdu
Date: Sun Jan 31 21:33:49 2010
New Revision: 905127

URL: http://svn.apache.org/viewvc?rev=905127&view=rev
Log:
Updating conversation for jira 137, 138, 240, 243

Modified:
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ConversationBean.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationImpl.java
    openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationManager.java
    openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/ConversationAwareViewHandler.java
    openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/WebBeansPhaseListener.java

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ConversationBean.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ConversationBean.java?rev=905127&r1=905126&r2=905127&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ConversationBean.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ConversationBean.java Sun Jan 31 21:33:49 2010
@@ -21,28 +21,41 @@
 import org.apache.webbeans.spi.ConversationService;
 import org.apache.webbeans.spi.ServiceLoader;
 
+/**
+ * Conversation bean implementation.
+ * @version $Rev$ $Date$
+ *
+ */
 public class ConversationBean extends AbstractBean<Conversation>
 {
-
+    /**
+     * Default constructor.
+     */
     public ConversationBean()
     {
         super(WebBeansType.CONVERSATION, Conversation.class);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected Conversation createInstance(CreationalContext<Conversation> creationalContext)
     {
-        ConversationService conversationService = ServiceLoader.getService(ConversationService.class);
-        
-        String conversationId = conversationService.getConversationId();
-        
-        String sessionId = conversationService.getConversationSessionId();
-        
         Conversation conversation = null;
+        //Gets conversation service
+        ConversationService conversationService = ServiceLoader.getService(ConversationService.class);        
+        //Gets conversation id
+        String conversationId = conversationService.getConversationId();       
+        //Gets session id that conversation is created
+        String sessionId = conversationService.getConversationSessionId();
 
+        //If conversation id is not null, this means that
+        //conversation is propogated
         if (conversationId != null)
         {
-            conversation = ConversationManager.getInstance().getConversation(conversationId,sessionId);
+            //Gets propogated conversation
+            conversation = ConversationManager.getInstance().getPropogatedConversation(conversationId,sessionId);
         }
         
         if (conversation == null)

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationImpl.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationImpl.java?rev=905127&r1=905126&r2=905127&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationImpl.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationImpl.java Sun Jan 31 21:33:49 2010
@@ -13,6 +13,9 @@
  */
 package org.apache.webbeans.conversation;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import javax.enterprise.context.Conversation;
 import javax.enterprise.context.ConversationScoped;
 
@@ -21,45 +24,76 @@
 import org.apache.webbeans.context.ConversationContext;
 import org.apache.webbeans.logger.WebBeansLogger;
 import org.apache.webbeans.util.Asserts;
-import org.apache.webbeans.util.StringUtil;
 
+/**
+ * Implementation of the {@link Conversation} interface.
+ * @version $Rev$ $Date$
+ *
+ */
 public class ConversationImpl implements Conversation
 {
+    /**Logger instance*/
     private static final WebBeansLogger logger = WebBeansLogger.getLogger(ConversationImpl.class);
     
+    /**Conversation id*/
     private String id;
 
+    /**Transient or not. Transient conversations are destroyed at the end of JSF request*/
     private boolean isTransient = true;
 
+    /**Default timeout is 3mins*/
     private long timeout = 30 * 60 * 1000 ;
 
+    /**Id of the session that this conversation is created*/
     private String sessionId;
 
+    /**Active duration of the conversation*/
     private long activeTime = 0L;
+    
+    /**Generating ids*/
+    private AtomicInteger conversationIdGenerator = new AtomicInteger(0);
+    
+    /**This instance is under used*/
+    private AtomicBoolean inUsed = new AtomicBoolean(false);
 
+    /**
+     * Default constructor. Used in tests.
+     */
     public ConversationImpl()
     {
-
     }
 
+    /**
+     * Creates a new conversation instance. Id is not
+     * set until conversation is begin.
+     * @param sessionId
+     */
     public ConversationImpl(String sessionId)
     {
         Asserts.assertNotNull(sessionId);
         this.sessionId = sessionId;
 
     }
-
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void begin()
     {
+        //Transient state
         if(this.isTransient)
         {
             this.isTransient = false;
-            this.id = StringUtil.generateUUIDStringWithoutDash();
-            
-            ConversationManager manager = ConversationManager.getInstance();
+            this.id = Integer.toString(this.conversationIdGenerator.incrementAndGet());
             
+            //Conversation manager
+            ConversationManager manager = ConversationManager.getInstance();            
             try
             {
+                //Gets current converation context instance.
+                //Each conversation has its own conversation context instance.
+                //Sets at the beginning of each JSF request.
                 manager.addConversationContext(this, (ConversationContext) BeanManagerImpl.getManager().getContext(ConversationScoped.class));
                 
             }catch(Exception e)
@@ -68,15 +102,27 @@
                 manager.addConversationContext(this, new ConversationContext());
             }            
         }
+        //Already started conversation.
         else
         {
             logger.warn(OWBLogConst.WARN_0006, new Object[]{id});
             throw new IllegalStateException();
         }
     }
-
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void begin(String id)
-    {
+    {   
+        //Look at other conversation, that may collate with this is
+        if(ConversationManager.getInstance().isConversationExistWithGivenId(id))
+        {
+            throw new IllegalArgumentException("Conversation with id=" + id + " is already exist!");
+        }
+        
+        //Transient state
         if(this.isTransient)
         {
             this.isTransient = false;
@@ -85,7 +131,11 @@
             ConversationManager.getInstance().addConversationContext(this, (ConversationContext) BeanManagerImpl.getManager().getContext(ConversationScoped.class));            
         }
     }
-
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void end()
     {
         if(!this.isTransient)
@@ -101,31 +151,72 @@
         }
     }
     
+    
+    /**
+     * @return the inUsed
+     */
+    public AtomicBoolean getInUsed()
+    {
+        return inUsed;
+    }
+
+    /**
+     * @param inUsed the inUsed to set
+     */
+    public void setInUsed(boolean inUsed)
+    {
+        this.inUsed.set(inUsed);
+    }
+    
+    /**
+     * Sets transient.
+     * @param value transient value
+     */
     public void setTransient(boolean value)
     {
         this.isTransient = value;
     }
-
+    
+    /**
+     * {@inheritDoc}
+     */    
+    @Override
     public String getId()
     {
         return this.id;
     }
 
+    /**
+     * {@inheritDoc}
+     */    
+    @Override
     public long getTimeout()
     {
         return this.timeout;
     }
 
+    /**
+     * {@inheritDoc}
+     */    
+    @Override
     public boolean isTransient()
     {
         return isTransient;
     }
-
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public void setTimeout(long milliseconds)
     {
         this.timeout = milliseconds;
     }
 
+    /**
+     * Gets session id.
+     * @return conversation session id
+     */
     public String getSessionId()
     {
         return this.sessionId;
@@ -140,6 +231,9 @@
     }
 
 
+    /**
+     * Update conversation timeout value.
+     */
     public void updateTimeOut()
     {
         this.activeTime = System.currentTimeMillis();

Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationManager.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationManager.java?rev=905127&r1=905126&r2=905127&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationManager.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/conversation/ConversationManager.java Sun Jan 31 21:33:49 2010
@@ -38,7 +38,7 @@
 public class ConversationManager
 {
     /**Current conversations*/
-    private Map<Conversation, ConversationContext> conversations = new ConcurrentHashMap<Conversation, ConversationContext>();
+    private ConcurrentHashMap<Conversation, ConversationContext> conversations = new ConcurrentHashMap<Conversation, ConversationContext>();
 
     /**
      * Creates new conversation manager
@@ -68,6 +68,32 @@
     {
         conversations.put(conversation, context);
     }
+    
+    /**
+     * Check conversation id exists.
+     * @param conversationId conversation id
+     * @return true if this conversation exist
+     */
+    public boolean isConversationExistWithGivenId(String conversationId)
+    {
+        synchronized (conversations)
+        {
+            ConversationImpl conv = null;
+            Set<Conversation> set = conversations.keySet();
+            Iterator<Conversation> it = set.iterator();
+
+            while (it.hasNext())
+            {
+                conv = (ConversationImpl) it.next();
+                if (conv.getId().equals(conversationId))
+                {
+                    return true;
+                }
+            }
+        }
+        
+        return false;
+    }
 
     /**
      * Remove given conversation.
@@ -99,7 +125,7 @@
      * @param sessionId session id
      * @return conversation
      */
-    public Conversation getConversation(String conversationId, String sessionId)
+    public Conversation getPropogatedConversation(String conversationId, String sessionId)
     {
         Asserts.assertNotNull(conversationId, "conversationId parameter can not be null");
         Asserts.assertNotNull(sessionId,"sessionId parameter can not be null");
@@ -152,7 +178,7 @@
      * @return conversation instance
      */
     @SuppressWarnings("unchecked")
-    public Conversation getConversationInstance()
+    public Conversation getConversationBeanReference()
     {
     	BeanManager beanManager = BeanManagerImpl.getManager();
         Bean<Conversation> bean = (Bean<Conversation>)beanManager.getBeans(Conversation.class, new DefaultLiteral()).iterator().next();

Modified: openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/ConversationAwareViewHandler.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/ConversationAwareViewHandler.java?rev=905127&r1=905126&r2=905127&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/ConversationAwareViewHandler.java (original)
+++ openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/ConversationAwareViewHandler.java Sun Jan 31 21:33:49 2010
@@ -41,7 +41,7 @@
     {
         String url = delegate.getActionURL(context, viewId);
 
-        Conversation conversation = conversationManager.getConversationInstance();
+        Conversation conversation = conversationManager.getConversationBeanReference();
         if (conversation != null && !conversation.isTransient())
         {
             url = JSFUtil.getRedirectViewIdWithCid(url, conversation.getId());

Modified: openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/WebBeansPhaseListener.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/WebBeansPhaseListener.java?rev=905127&r1=905126&r2=905127&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/WebBeansPhaseListener.java (original)
+++ openwebbeans/trunk/webbeans-jsf/src/main/java/org/apache/webbeans/jsf/WebBeansPhaseListener.java Sun Jan 31 21:33:49 2010
@@ -13,10 +13,13 @@
  */
 package org.apache.webbeans.jsf;
 
+import javax.enterprise.context.BusyConversationException;
 import javax.enterprise.context.Conversation;
+import javax.enterprise.context.NonexistentConversationException;
 import javax.faces.event.PhaseEvent;
 import javax.faces.event.PhaseId;
 import javax.faces.event.PhaseListener;
+import javax.servlet.http.HttpServletRequest;
 
 import org.apache.webbeans.config.OWBLogConst;
 import org.apache.webbeans.context.ContextFactory;
@@ -49,7 +52,7 @@
     {
         if (phaseEvent.getPhaseId().equals(PhaseId.RENDER_RESPONSE))
         {
-        	Conversation conversation = conversationManager.getConversationInstance();
+        	Conversation conversation = conversationManager.getConversationBeanReference();
         	
             if (conversation.isTransient())
             {
@@ -58,7 +61,17 @@
             }
             else
             {
-            	((ConversationImpl) conversation).updateTimeOut();
+                //Conversation must be used by one thread at a time
+                ConversationImpl owbConversation = (ConversationImpl)conversation;
+                owbConversation.updateTimeOut();
+                //Other threads can now access propogated conversation.
+                owbConversation.setInUsed(false);                
+            }
+            
+            HttpServletRequest request = (HttpServletRequest)phaseEvent.getFacesContext().getExternalContext().getRequest();
+            if(request.getMethod().equals("POST"))
+            {
+                JSFUtil.getSession().removeAttribute("POST_CONVERSATION");
             }
         }
     }
@@ -68,20 +81,63 @@
      */
     public void beforePhase(PhaseEvent phaseEvent)
     {
+        HttpServletRequest request = (HttpServletRequest)phaseEvent.getFacesContext().getExternalContext().getRequest();
+        
         if (phaseEvent.getPhaseId().equals(PhaseId.RESTORE_VIEW))
         {
-        	Conversation conversation = conversationManager.getConversationInstance();
-
+            if(request.getMethod().equals("POST"))
+            {
+                JSFUtil.getSession().setAttribute("POST_CONVERSATION", true);
+            }
+            
+            //It looks for cid parameter in the JSF request.
+            //If request contains cid, then it must restore conversation
+            //Otherwise create NonexistentException
+        	Conversation conversation = conversationManager.getConversationBeanReference();
+        	String cid = JSFUtil.getConversationId();
+        	
 			if (conversation.isTransient())
 			{
 				logger.info(OWBLogConst.INFO_0043, new Object[]{conversation.getId(), JSFUtil.getViewId()});
 				ContextFactory.initConversationContext(null);
+				
+	            //Not restore, throw exception
+				if(cid != null && !cid.equals(""))
+				{
+				    throw new NonexistentConversationException("Propogated conversation with cid=" + cid + " is not restored. It creates a new transient conversation.");
+				}
 			}
 			else
 			{
 				logger.info(OWBLogConst.INFO_0042, new Object[]{conversation.getId(), JSFUtil.getViewId()});
-				ConversationContext conversationContext = conversationManager.getConversationContext(conversation);
-				ContextFactory.initConversationContext(conversationContext);
+				
+				//Conversation must be used by one thread at a time
+				ConversationImpl owbConversation = (ConversationImpl)conversation;
+				if(!owbConversation.getInUsed().compareAndSet(false, true))
+				{
+				    if(request.getMethod().equals("GET"))
+				    {
+				        //POST-Redirect-GET
+				        if(JSFUtil.getSession().getAttribute("POST_CONVERSATION") != null)
+				        {
+			                   ConversationContext conversationContext = conversationManager.getConversationContext(conversation);
+			                   ContextFactory.initConversationContext(conversationContext);
+			                   
+			                   JSFUtil.getSession().removeAttribute("POST_CONVERSATION");
+			                   
+			                   return;
+				        }
+				    }
+				    
+				    ContextFactory.initConversationContext(null);
+				    //Throw Busy exception
+				    throw new BusyConversationException("Propogated conversation with cid=" + cid + " is used by other request. It creates a new transient conversation");
+				}
+				else
+				{
+	               ConversationContext conversationContext = conversationManager.getConversationContext(conversation);
+	               ContextFactory.initConversationContext(conversationContext);
+				}				
 			}
         }
     }