You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by st...@apache.org on 2012/07/28 02:13:41 UTC

svn commit: r1366570 - in /openwebbeans/trunk/webbeans-impl/src: main/java/org/apache/webbeans/decorator/ main/java/org/apache/webbeans/intercept/ main/java/org/apache/webbeans/lifecycle/test/ test/java/org/apache/webbeans/newtests/decorators/tests/

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();
                 }