Author: struberg
Date: Mon Mar 7 23:20:07 2011
New Revision: 1079019
URL: http://svn.apache.org/viewvc?rev=1079019&view=rev
Log:
OWB-530 fix concurrency problem and cleanup CreationalContext
this also blasts away an ugly public static ThreadLocal.
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractOwbBean.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/CreationalContextImpl.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/DependentCreationalContext.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/InjectableMethods.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/disposes/beans/DependentBean.java
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractOwbBean.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractOwbBean.java?rev=1079019&r1=1079018&r2=1079019&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractOwbBean.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractOwbBean.java
Mon Mar 7 23:20:07 2011
@@ -236,22 +236,13 @@ public abstract class AbstractOwbBean<T>
destroyInstance(instance,creationalContext);
}
- //Setting destroying instance
- CreationalContextImpl.currentRemoveObject.set(instance);
-
//Destory dependent instances
- creationalContext.release();
-
+ creationalContext.release();
}
catch(Exception e)
{
getLogger().fatal(e, OWBLogConst.FATAL_0001, this);
}
- finally
- {
- CreationalContextImpl.currentRemoveObject.set(null);
- CreationalContextImpl.currentRemoveObject.remove();
- }
}
/**
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/CreationalContextImpl.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/CreationalContextImpl.java?rev=1079019&r1=1079018&r2=1079019&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/CreationalContextImpl.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/CreationalContextImpl.java
Mon Mar 7 23:20:07 2011
@@ -30,6 +30,7 @@ import javax.enterprise.inject.spi.Inter
import org.apache.webbeans.config.WebBeansContext;
import
org.apache.webbeans.context.creational.DependentCreationalContext.DependentType;
+import org.apache.webbeans.exception.WebBeansException;
import org.apache.webbeans.util.Asserts;
import org.apache.webbeans.util.WebBeansUtil;
@@ -48,17 +49,19 @@ public class CreationalContextImpl<T> im
private Map<Object, List<DependentCreationalContext<?>>> dependentObjects
= null;
/**Contextual bean*/
- private volatile Contextual<T> contextual = null;
+ private Contextual<T> contextual = null;
/**Ejb interceptors*/
//contextual instance --> interceptors
private ConcurrentMap<Object, List<EjbInterceptorContext>> ejbInterceptors
= null;
- /**When bean object is destroyed it is set*/
- //X TODO refactor. public static variables are utterly ugly
- public static ThreadLocal<Object> currentRemoveObject = new
ThreadLocal<Object>();
-
private WebBeansContext webBeansContext;
+
+ /**
+ * This flag will get set to <code>true</code> to prevent recursive loops
while destroying
+ * the CreationContext.
+ */
+ private boolean destroying = false;
/**
* Package private
@@ -146,13 +149,14 @@ public class CreationalContextImpl<T> im
/**
* Adds given dependent instance to the map.
*
+ * @param ownerInstance the contextual instance our dependent instance got
injected into
* @param dependent dependent contextual
* @param instance dependent instance
*/
public <K> void addDependent(Object ownerInstance, Contextual<K>
dependent, Object instance)
{
Asserts.assertNotNull(dependent,"dependent parameter cannot be null");
-
+
if(instance != null)
{
DependentCreationalContext<K> dependentCreational = new
DependentCreationalContext<K>(dependent);
@@ -259,59 +263,17 @@ public class CreationalContextImpl<T> im
}
}
return null;
- }
-
- /**
- * Removes dependent objects.
- */
- @SuppressWarnings("unchecked")
- public void removeDependents(Object ownerInstance)
- {
- if(ownerInstance == null || dependentObjects == null)
- {
- return;
- }
-
-
- synchronized(this)
- {
- List<DependentCreationalContext<?>> values =
this.dependentObjects.get(ownerInstance);
- if(values != null)
- {
- final CreationalContextFactory contextFactory =
webBeansContext.getCreationalContextFactory();
- Iterator<?> iterator = values.iterator();
- while(iterator.hasNext())
- {
- DependentCreationalContext<T> dependent =
(DependentCreationalContext<T>)iterator.next();
-
dependent.getContextual().destroy((T)dependent.getInstance(),
contextFactory.getCreationalContext(dependent.getContextual()));
- }
-
- this.dependentObjects.remove(ownerInstance);
- }
- }
-
- if (this.ejbInterceptors != null)
- {
- List<EjbInterceptorContext> interceptors =
this.ejbInterceptors.get(ownerInstance);
- if(interceptors != null)
- {
- for(EjbInterceptorContext intereptor : interceptors)
- {
- intereptor.getInjectorInstance().destroy();
- }
- }
-
- this.ejbInterceptors.remove(ownerInstance);
- }
}
-
+
@SuppressWarnings("unchecked")
public void removeAllDependents()
{
- if (dependentObjects == null)
+ if (dependentObjects == null || destroying)
{
return;
}
+
+ destroying = true;
synchronized(this)
{
@@ -320,12 +282,22 @@ public class CreationalContextImpl<T> im
{
for(List<DependentCreationalContext<?>> value : values)
{
- Iterator<?> iterator = value.iterator();
- while(iterator.hasNext())
+ // this is kind of an emergency valve...
+ int maxRemoval = value.size() * 3;
+ while(!value.isEmpty() && maxRemoval > 0)
+ {
+ // we don't use an iterator because the destroyal
might register a
+ // fresh PreDestroy interceptor as dependent object...
+ DependentCreationalContext<T> dependent =
(DependentCreationalContext<T>)value.get(0);
+
dependent.getContextual().destroy((T)dependent.getInstance(), this);
+
+ value.remove(0);
+ maxRemoval--;
+ }
+
+ if (maxRemoval == 0)
{
- DependentCreationalContext<T> dependent =
(DependentCreationalContext<T>)iterator.next();
- CreationalContextFactory contextFactory =
webBeansContext.getCreationalContextFactory();
-
dependent.getContextual().destroy((T)dependent.getInstance(),
contextFactory.getCreationalContext(dependent.getContextual()));
+ throw new WebBeansException("infinite loop detected
while destroying bean " + contextual);
}
}
}
@@ -362,14 +334,7 @@ public class CreationalContextImpl<T> im
@Override
public void release()
{
- if(currentRemoveObject.get() == null)
- {
- removeAllDependents();
- }
- else
- {
- removeDependents(currentRemoveObject.get());
- }
+ removeAllDependents();
}
/**
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/DependentCreationalContext.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/DependentCreationalContext.java?rev=1079019&r1=1079018&r2=1079019&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/DependentCreationalContext.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/context/creational/DependentCreationalContext.java
Mon Mar 7 23:20:07 2011
@@ -29,6 +29,10 @@ import javax.enterprise.context.spi.Cont
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.util.WebBeansUtil;
+/**
+ * This class contains creation information about @Dependent scoped
+ * contextual instances.
+ */
public class DependentCreationalContext<S> implements Serializable
{
private static final long serialVersionUID = 1L;
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java?rev=1079019&r1=1079018&r2=1079019&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/AbstractInjectable.java
Mon Mar 7 23:20:07 2011
@@ -145,9 +145,9 @@ public abstract class AbstractInjectable
if(instanceUnderInjection.get() != null)
{
((CreationalContextImpl<?>)this.injectionOwnerCreationalContext).addDependent(instanceUnderInjection.get(),injectedBean,
injected);
- }
+ }
}
-
+
return injected;
}
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/InjectableMethods.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/InjectableMethods.java?rev=1079019&r1=1079018&r2=1079019&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/InjectableMethods.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/inject/InjectableMethods.java
Mon Mar 7 23:20:07 2011
@@ -36,7 +36,6 @@ import org.apache.webbeans.annotation.De
import org.apache.webbeans.component.OwbBean;
import org.apache.webbeans.component.ProducerMethodBean;
import org.apache.webbeans.container.InjectionResolver;
-import org.apache.webbeans.context.creational.CreationalContextImpl;
import org.apache.webbeans.exception.WebBeansException;
import org.apache.webbeans.util.SecurityUtil;
@@ -147,15 +146,6 @@ public class InjectableMethods<T> extend
}
}
- /**
- * Destroy dependent objects of the bean.
- */
- public void destroyDependentInjectionPoints(Object ownerInstance)
- {
- CreationalContextImpl<?> ownerCreational = (CreationalContextImpl<?>)
this.injectionOwnerCreationalContext;
- ownerCreational.removeDependents(ownerInstance);
- }
-
public Map<Bean<?>,Object> getDependentBeanParameters()
{
return this.dependentParameters;
Modified:
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/disposes/beans/DependentBean.java
URL:
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/disposes/beans/DependentBean.java?rev=1079019&r1=1079018&r2=1079019&view=diff
==============================================================================
---
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/disposes/beans/DependentBean.java
(original)
+++
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/disposes/beans/DependentBean.java
Mon Mar 7 23:20:07 2011
@@ -45,7 +45,7 @@ public class DependentBean
model.setValue(true);
model.setId(index++);
if (producedModel == null) {
- producedModel = model;
+ producedModel = model;
}
System.out.println("produced DependentModel=" + model);
return model;