You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by st...@apache.org on 2012/09/29 18:55:50 UTC

git commit: DELTASPIKE-274 atomic contextual instance creation

Updated Branches:
  refs/heads/master b45b2daa9 -> b29dab065


DELTASPIKE-274 atomic contextual instance creation


Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/b29dab06
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/b29dab06
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/b29dab06

Branch: refs/heads/master
Commit: b29dab06520a12cd6cc382df01d79234b406008e
Parents: b45b2da
Author: Mark Struberg <st...@apache.org>
Authored: Sat Sep 29 18:54:35 2012 +0200
Committer: Mark Struberg <st...@apache.org>
Committed: Sat Sep 29 18:54:35 2012 +0200

----------------------------------------------------------------------
 .../core/util/context/AbstractContext.java         |   67 +++++++++++----
 .../core/util/context/ContextualInstanceInfo.java  |   21 +++--
 .../core/util/context/ContextualStorage.java       |   66 ++++++++++++++
 3 files changed, 132 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/b29dab06/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java
index 7d65d44..7a02cf5 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/AbstractContext.java
@@ -19,10 +19,10 @@
 
 package org.apache.deltaspike.core.util.context;
 
+import javax.enterprise.context.ContextNotActiveException;
 import javax.enterprise.context.spi.Context;
 import javax.enterprise.context.spi.Contextual;
 import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.spi.BeanManager;
 import java.lang.annotation.Annotation;
 import java.util.Map;
 
@@ -32,19 +32,13 @@ import java.util.Map;
 public abstract class AbstractContext implements Context
 {
     /**
-     * We need the BeanManager for serialisation and some checks.
-     */
-    protected BeanManager beanManager;
-
-    /**
      * The Scope the Context handles
      */
     protected Class<? extends Annotation> scope;
 
 
-    protected AbstractContext(BeanManager beanManager, Class<? extends Annotation> scope, boolean concurrent)
+    protected AbstractContext(Class<? extends Annotation> scope)
     {
-        this.beanManager = beanManager;
         this.scope = scope;
     }
 
@@ -53,7 +47,7 @@ public abstract class AbstractContext implements Context
      * contains the items held in the Context.
      * @return the underlying storage
      */
-    protected abstract ContextualStorage getContextStorage();
+    protected abstract ContextualStorage getContextualStorage();
 
 
     @Override
@@ -64,15 +58,48 @@ public abstract class AbstractContext implements Context
 
 
     @Override
-    public <T> T get(Contextual<T> component)
+    public <T> T get(Contextual<T> bean)
     {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        checkActive();
+
+        if (getContextualStorage() == null)
+        {
+            return null;
+        }
+
+        Map<Contextual<?>, ContextualInstanceInfo<?>> contextMap = getContextualStorage().getStorage();
+        ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(bean);
+        if (contextualInstanceInfo == null)
+        {
+            return null;
+        }
+
+        return (T) contextualInstanceInfo.getContextualInstance();
     }
 
     @Override
-    public <T> T get(Contextual<T> component, CreationalContext<T> creationalContext)
+    public <T> T get(Contextual<T> bean, CreationalContext<T> creationalContext)
     {
-        return null;  //To change body of implemented methods use File | Settings | File Templates.
+        checkActive();
+
+        ContextualStorage storage = getContextualStorage();
+
+        Map<Contextual<?>, ContextualInstanceInfo<?>> contextMap = storage.getStorage();
+        ContextualInstanceInfo<?> contextualInstanceInfo = contextMap.get(bean);
+
+        T instance = null;
+
+        if (contextualInstanceInfo != null)
+        {
+            instance =  (T) contextualInstanceInfo.getContextualInstance();
+        }
+
+        if (instance != null)
+        {
+            return instance;
+        }
+
+        return storage.createContextualInstance(bean, creationalContext);
     }
 
     /**
@@ -82,7 +109,7 @@ public abstract class AbstractContext implements Context
      */
     public boolean destroy(Contextual bean)
     {
-        ContextualInstanceInfo<?> contextualInstanceInfo = getContextStorage().getStorage().get(bean);
+        ContextualInstanceInfo<?> contextualInstanceInfo = getContextualStorage().getStorage().get(bean);
 
         if (contextualInstanceInfo == null)
         {
@@ -99,15 +126,23 @@ public abstract class AbstractContext implements Context
      */
     public void destroyAll()
     {
-        Map<Contextual<?>, ContextualInstanceInfo<?>> storage = getContextStorage().getStorage();
+        Map<Contextual<?>, ContextualInstanceInfo<?>> storage = getContextualStorage().getStorage();
         for (Map.Entry<Contextual<?>, ContextualInstanceInfo<?>> entry : storage.entrySet())
         {
             Contextual bean = entry.getKey();
             ContextualInstanceInfo<?> contextualInstanceInfo = entry.getValue();
             bean.destroy(contextualInstanceInfo.getContextualInstance(), contextualInstanceInfo.getCreationalContext());
         }
+    }
 
-
+    protected void checkActive()
+    {
+        if (!isActive())
+        {
+            throw new ContextNotActiveException("CDI context with scope annotation @"
+                + scope.getName() + " is not active with respect to the current thread");
+        }
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/b29dab06/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java
index 34188c4..090cf2b 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualInstanceInfo.java
@@ -42,12 +42,6 @@ public class ContextualInstanceInfo<T> implements Serializable
 
 
 
-    public ContextualInstanceInfo(CreationalContext<T> creationalContext, T contextualInstance)
-    {
-        this.contextualInstance = contextualInstance;
-        this.creationalContext = creationalContext;
-    }
-
     /**
      * @return the CreationalContext of the bean
      */
@@ -57,6 +51,14 @@ public class ContextualInstanceInfo<T> implements Serializable
     }
 
     /**
+     * @param creationalContext the CreationalContext of the bean
+     */
+    public void setCreationalContext(CreationalContext<T> creationalContext)
+    {
+        this.creationalContext = creationalContext;
+    }
+
+    /**
      * @return the contextual instance itself
      */
     public T getContextualInstance()
@@ -64,6 +66,13 @@ public class ContextualInstanceInfo<T> implements Serializable
         return contextualInstance;
     }
 
+    /**
+     * @param contextualInstance the contextual instance itself
+     */
+    public void setContextualInstance(T contextualInstance)
+    {
+        this.contextualInstance = contextualInstance;
+    }
 
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/b29dab06/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualStorage.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualStorage.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualStorage.java
index a155f24..3a03fce 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualStorage.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/context/ContextualStorage.java
@@ -21,6 +21,7 @@ package org.apache.deltaspike.core.util.context;
 
 
 import javax.enterprise.context.spi.Contextual;
+import javax.enterprise.context.spi.CreationalContext;
 import javax.enterprise.inject.spi.BeanManager;
 import javax.enterprise.inject.spi.PassivationCapable;
 import java.io.IOException;
@@ -48,6 +49,10 @@ public class ContextualStorage implements Serializable
 
     private boolean concurrent;
 
+    /**
+     * @param beanManager is needed for serialisation
+     * @param concurrent whether the ContextualStorage might get accessed concurrently by different threads
+     */
     public ContextualStorage(BeanManager beanManager, boolean concurrent)
     {
         this.beanManager = beanManager;
@@ -62,12 +67,23 @@ public class ContextualStorage implements Serializable
         }
     }
 
+    /**
+     * @return the underlying storage map.
+     */
     public Map<Contextual<?>, ContextualInstanceInfo<?>> getStorage()
     {
         return contextualInstances;
     }
 
     /**
+     * Whether the ContextualStorage might get accessed concurrently by different threads
+     */
+    public boolean isConcurrent()
+    {
+        return concurrent;
+    }
+
+    /**
      * Write the whole map to the stream.
      * The beans will be stored via it's passivationId as it is
      * not guaranteed that a Bean is Serializable in CDI-1.0.
@@ -137,4 +153,54 @@ public class ContextualStorage implements Serializable
         }
     }
 
+    /**
+     *
+     * @param bean
+     * @param creationalContext
+     * @param <T>
+     * @return
+     */
+    public <T> T createContextualInstance(Contextual<T> bean, CreationalContext<T> creationalContext)
+    {
+        if (isConcurrent())
+        {
+            // locked approach
+            ContextualInstanceInfo<T> instanceInfo = new ContextualInstanceInfo<T>();
+
+            ConcurrentHashMap<Contextual<?>, ContextualInstanceInfo<?>> concurrentMap
+                = (ConcurrentHashMap<Contextual<?>, ContextualInstanceInfo<?>>) contextualInstances;
+
+            ContextualInstanceInfo<T> oldInstanceInfo
+                = (ContextualInstanceInfo<T>) concurrentMap.putIfAbsent(bean, instanceInfo);
+
+            if (oldInstanceInfo != null)
+            {
+                instanceInfo = oldInstanceInfo;
+            }
+            synchronized (instanceInfo)
+            {
+                T instance = instanceInfo.getContextualInstance();
+                if (instance == null)
+                {
+                    instance = bean.create(creationalContext);
+                    instanceInfo.setContextualInstance(instance);
+                    instanceInfo.setCreationalContext(creationalContext);
+                }
+
+                return instance;
+            }
+
+        }
+        else
+        {
+            // simply create the contextual instance
+            ContextualInstanceInfo<T> instanceInfo = new ContextualInstanceInfo<T>();
+            instanceInfo.setCreationalContext(creationalContext);
+            instanceInfo.setContextualInstance(bean.create(creationalContext));
+
+            contextualInstances.put(bean, instanceInfo);
+
+            return instanceInfo.getContextualInstance();
+        }
+    }
 }