Author: struberg
Date: Sat Jul 28 00:13:40 2012
New Revision: 1366570

URL: http://svn.apache.org/viewvc?rev=1366570&view=rev
Log:
OWB-672 fix Decorator concurrency problems

We only need to create the Decorator stack once, as Decorators
are @Dependent beans to the decorated instance.

Modified:
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DelegateHandler.java
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/WebBeansDecoratorConfig.java
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorHandler.java
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/test/OpenWebBeansTestMetaDataDiscoveryService.java
    
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/decorators/tests/DecoratorAndInterceptorStackTests.java

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DelegateHandler.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DelegateHandler.java?rev=1366570&r1=1366569&r2=1366570&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DelegateHandler.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/DelegateHandler.java
 Sat Jul 28 00:13:40 2012
@@ -26,6 +26,7 @@ import java.io.ObjectOutput;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -46,7 +47,14 @@ public class DelegateHandler implements 
     private static final Logger logger = 
WebBeansLoggerFacade.getLogger(DelegateHandler.class);
 
     private transient List<Object> decorators;
-    private transient int position = 0;
+    private transient ThreadLocal<AtomicInteger> position = new 
ThreadLocal<AtomicInteger>()
+    {
+        @Override
+        protected AtomicInteger initialValue()
+        {
+            return new AtomicInteger(0);
+        }
+    };
 
     private transient Object actualInstance = null;
     
@@ -79,10 +87,10 @@ public class DelegateHandler implements 
             actualInstance = instance;
         }
 
-        while (position < decorators.size())
+        while (position.get().intValue() < decorators.size())
         {
 
-            Object decorator = decorators.get(position++);
+            Object decorator = 
decorators.get(position.get().getAndIncrement());
 
             try
             {
@@ -97,7 +105,7 @@ public class DelegateHandler implements 
                     }
 
                     Object returnValue = decMethod.invoke(decorator, 
arguments);
-                    position--;
+                    position.remove();
                     return returnValue;
                 }
 
@@ -120,7 +128,7 @@ public class DelegateHandler implements 
                 {
                     continue;
                 }
-                
+
                 logger.log(Level.SEVERE, OWBLogConst.ERROR_0012, 
WebBeansLoggerFacade.args(e.getTargetException(), method.getName(), 
decorator.getClass().getName()));
 
                 if (cause instanceof Exception)
@@ -144,6 +152,8 @@ public class DelegateHandler implements 
 
         }
 
+        position.remove();
+
         if (!method.isAccessible())
         {
             
bean.getWebBeansContext().getSecurityService().doPrivilegedSetAccessible(method,
 true);

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/WebBeansDecoratorConfig.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/WebBeansDecoratorConfig.java?rev=1366570&r1=1366569&r2=1366570&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/WebBeansDecoratorConfig.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/decorator/WebBeansDecoratorConfig.java
 Sat Jul 28 00:13:40 2012
@@ -145,34 +145,34 @@ public final class WebBeansDecoratorConf
     public static List<Object> getDecoratorStack(InjectionTargetBean<?> 
component, Object instance, 
             Object delegate, CreationalContextImpl<?> ownerCreationalContext)
     {
-        List<Object> decoratorStack = new ArrayList<Object>();
-        List<Decorator<?>> decoratorList = component.getDecoratorStack();      
  
-        Iterator<Decorator<?>> itList = decoratorList.iterator();
-        BeanManager manager = 
component.getWebBeansContext().getBeanManagerImpl();
-        while (itList.hasNext())
+        // we need to synchronize on the instance to prevent
+        // creating the decorators too often
+        synchronized(instance)
         {
-            Object decoratorInstance ;
-            WebBeansDecorator<Object> decorator = (WebBeansDecorator<Object>) 
itList.next();
-            decoratorInstance = 
ownerCreationalContext.getDependentDecorator(instance, decorator);
-            if(decoratorInstance == null)
+            List<Object> decoratorStack = new ArrayList<Object>();
+            List<Decorator<?>> decoratorList = component.getDecoratorStack();
+            Iterator<Decorator<?>> itList = decoratorList.iterator();
+            BeanManager manager = 
component.getWebBeansContext().getBeanManagerImpl();
+            while (itList.hasNext())
             {
-                decoratorInstance = manager.getReference(decorator, 
decorator.getBeanClass(), ownerCreationalContext);
-                
-                decorator.setInjections(decoratorInstance, 
ownerCreationalContext);
-                decorator.setDelegate(decoratorInstance, delegate);
-                
-                ownerCreationalContext.addDependent(instance, decorator, 
decoratorInstance);
-            }
-            else
-            {
-                //We found an existing decorator instance, update the delegate
-                decorator.setDelegate(decoratorInstance, delegate);
+                Object decoratorInstance ;
+                WebBeansDecorator<Object> decorator = 
(WebBeansDecorator<Object>) itList.next();
+                decoratorInstance = 
ownerCreationalContext.getDependentDecorator(instance, decorator);
+                if(decoratorInstance == null)
+                {
+                    decoratorInstance = manager.getReference(decorator, 
decorator.getBeanClass(), ownerCreationalContext);
+
+                    decorator.setInjections(decoratorInstance, 
ownerCreationalContext);
+                    decorator.setDelegate(decoratorInstance, delegate);
+
+                    ownerCreationalContext.addDependent(instance, decorator, 
decoratorInstance);
+                }
+
+                decoratorStack.add(decoratorInstance);
             }
-            
-            decoratorStack.add(decoratorInstance);
-        }
 
-        return decoratorStack;
+            return decoratorStack;
+        }
     }
 
     public static Set<Decorator<?>> 
findDeployedWebBeansDecorator(BeanManagerImpl beanManagerImpl, Set<Type> 
apiType, Annotation... anns)

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorHandler.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorHandler.java?rev=1366570&r1=1366569&r2=1366570&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorHandler.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorHandler.java
 Sat Jul 28 00:13:40 2012
@@ -156,6 +156,8 @@ public abstract class InterceptorHandler
 
     protected WebBeansContext webBeansContext;
 
+    private volatile DelegateHandler delegateHandler = null;
+
     /**
      * Creates a new handler.
      * @param bean proxied bean
@@ -225,30 +227,34 @@ public abstract class InterceptorHandler
                 !ClassUtil.isObjectMethod(methodName) && bean instanceof 
InjectionTargetBean<?>)
             {
                 InjectionTargetBean<?> injectionTarget = 
(InjectionTargetBean<?>) bean;
-                DelegateHandler delegateHandler = null;
                 InterceptorDataImpl decoratorInterceptorDataImpl = null;
                 
                 //Check method is business method
                 if 
(webBeansContext.getInterceptorUtil().isWebBeansBusinessMethod(method))
                 {
-                    List<Object> decorators = null;
                     if (!injectionTarget.getDecoratorStack().isEmpty())
                     {
-                        Class<?> proxyClass = 
webBeansContext.getJavassistProxyFactory().getInterceptorProxyClasses().get(bean);
-                        if (proxyClass == null)
+                        synchronized (this)
                         {
-                            ProxyFactory delegateFactory = 
webBeansContext.getJavassistProxyFactory().createProxyFactory(bean);
-                            proxyClass = 
webBeansContext.getJavassistProxyFactory().getProxyClass(delegateFactory);
-                            
webBeansContext.getJavassistProxyFactory().getInterceptorProxyClasses().put(bean,
 proxyClass);
+                            if (delegateHandler == null)
+                            {
+                                Class<?> proxyClass = 
webBeansContext.getJavassistProxyFactory().getInterceptorProxyClasses().get(bean);
+                                if (proxyClass == null)
+                                {
+                                    ProxyFactory delegateFactory = 
webBeansContext.getJavassistProxyFactory().createProxyFactory(bean);
+                                    proxyClass = 
webBeansContext.getJavassistProxyFactory().getProxyClass(delegateFactory);
+                                    
webBeansContext.getJavassistProxyFactory().getInterceptorProxyClasses().put(bean,
 proxyClass);
+                                }
+                                Object delegate = proxyClass.newInstance();
+                                delegateHandler = new DelegateHandler(bean);
+                                
((ProxyObject)delegate).setHandler(delegateHandler);
+
+                                // Gets component decorator stack
+                                List<Object> decorators = 
WebBeansDecoratorConfig.getDecoratorStack(injectionTarget, instance, delegate, 
ownerCreationalContext);
+                                //Sets decorator stack of delegate
+                                delegateHandler.setDecorators(decorators);
+                            }
                         }
-                        Object delegate = proxyClass.newInstance();
-                        delegateHandler = new DelegateHandler(bean);
-                        ((ProxyObject)delegate).setHandler(delegateHandler);
-
-                        // Gets component decorator stack
-                        decorators = 
WebBeansDecoratorConfig.getDecoratorStack(injectionTarget, instance, delegate, 
ownerCreationalContext);                        
-                        //Sets decorator stack of delegate
-                        delegateHandler.setDecorators(decorators);
                     }
 
                     // Run around invoke chain
@@ -261,7 +267,7 @@ public abstract class InterceptorHandler
                             interceptedMethodMap = new 
ConcurrentHashMap<Method, List<InterceptorData>>();
                         }
                         
-                        if (decorators != null)
+                        if (delegateHandler != null)
                         {
                             // We have interceptors and decorators, Our 
delegateHandler will need to be wrapped in an interceptor
                             WebBeansDecoratorInterceptor lastInterceptor = new 
WebBeansDecoratorInterceptor(delegateHandler, instance);
@@ -310,7 +316,7 @@ public abstract class InterceptorHandler
                     
                     // If there are Decorators, allow the delegate handler to
                     // manage the stack
-                    if (decorators != null)
+                    if (delegateHandler != null)
                     {
                         return delegateHandler.invoke(instance, method, 
proceed, arguments);
                     }

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/test/OpenWebBeansTestMetaDataDiscoveryService.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/test/OpenWebBeansTestMetaDataDiscoveryService.java?rev=1366570&r1=1366569&r2=1366570&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/test/OpenWebBeansTestMetaDataDiscoveryService.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/test/OpenWebBeansTestMetaDataDiscoveryService.java
 Sat Jul 28 00:13:40 2012
@@ -22,11 +22,14 @@ import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javassist.ClassPool;
 
 import org.apache.webbeans.corespi.scanner.AbstractMetaDataDiscovery;
 import org.apache.webbeans.exception.WebBeansDeploymentException;
+import org.apache.webbeans.logger.WebBeansLoggerFacade;
 import org.apache.webbeans.util.Asserts;
 
 /**
@@ -36,6 +39,8 @@ import org.apache.webbeans.util.Asserts;
  */
 public class OpenWebBeansTestMetaDataDiscoveryService extends 
AbstractMetaDataDiscovery
 {
+    private static final Logger logger = 
WebBeansLoggerFacade.getLogger(OpenWebBeansTestMetaDataDiscoveryService.class);
+
     public OpenWebBeansTestMetaDataDiscoveryService()
     {
         
@@ -101,7 +106,7 @@ public class OpenWebBeansTestMetaDataDis
         }
         catch (IOException e)
         {
-            e.printStackTrace();
+            logger.log(Level.WARNING, "Problems while scanning class " + 
clazz.getName());
         }
     }
     

Modified: 
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/decorators/tests/DecoratorAndInterceptorStackTests.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/decorators/tests/DecoratorAndInterceptorStackTests.java?rev=1366570&r1=1366569&r2=1366570&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/decorators/tests/DecoratorAndInterceptorStackTests.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/decorators/tests/DecoratorAndInterceptorStackTests.java
 Sat Jul 28 00:13:40 2012
@@ -45,7 +45,7 @@ public class DecoratorAndInterceptorStac
 {
 
     public static final String PACKAGE_NAME = 
DecoratorAndInterceptorStackTests.class.getPackage().getName();
-    private static final int NUM_THREADS = 50;
+    private static final int NUM_THREADS = 20;
 
     private static final Logger log = 
Logger.getLogger(DecoratorAndInterceptorStackTests.class.getName());
 
@@ -82,7 +82,7 @@ public class DecoratorAndInterceptorStac
     }
 
 
-    //X TODO @Test
+    @Test
     public void testParallelInterceptorInvocation() throws Exception
     {
         Collection<Class<?>> classes = new ArrayList<Class<?>>();
@@ -106,6 +106,7 @@ public class DecoratorAndInterceptorStac
         for (int i= 0 ; i < NUM_THREADS; i++)
         {
             threads[i] = new InterceptorTestRunner(outsideBean);
+            threads[i].setName("testthread_" + i);
             threads[i].start();
         }
 
@@ -136,7 +137,7 @@ public class DecoratorAndInterceptorStac
                 // this starts the RequestContext for this very thread
                 
WebBeansContext.currentInstance().getContextFactory().initRequestContext(null);
 
-                for (int i=0; i < 5; i++)
+                for (int i=0; i < 10; i++)
                 {
                     outsideBean.doThaStuff();
                 }


Reply via email to