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