You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by jo...@apache.org on 2016/07/13 23:51:28 UTC

deltaspike git commit: DELTASPIKE-1183 Fix concurrency issue when using proxies.

Repository: deltaspike
Updated Branches:
  refs/heads/master db8560c41 -> f2985d502


DELTASPIKE-1183 Fix concurrency issue when using proxies.


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

Branch: refs/heads/master
Commit: f2985d5022a04dce005ee3540a350822d4987a3b
Parents: db8560c
Author: John D. Ament <jo...@apache.org>
Authored: Wed Jul 13 19:51:23 2016 -0400
Committer: John D. Ament <jo...@apache.org>
Committed: Wed Jul 13 19:51:23 2016 -0400

----------------------------------------------------------------------
 .../core/api/partialbean/uc012/BlockPolicy.java |  39 +++++++
 .../partialbean/uc012/ConcurrencyBugTest.java   | 109 +++++++++++++++++++
 .../partialbean/uc012/MyPartialBeanBinding.java |  32 ++++++
 .../partialbean/uc012/MyPartialBeanHandler.java |  32 ++++++
 .../core/api/partialbean/uc012/PartialBean.java |  29 +++++
 .../AbstractManualInvocationHandler.java        |  37 ++-----
 6 files changed, 248 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f2985d50/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/BlockPolicy.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/BlockPolicy.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/BlockPolicy.java
new file mode 100644
index 0000000..2f9af70
--- /dev/null
+++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/BlockPolicy.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.deltaspike.test.core.api.partialbean.uc012;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+public class BlockPolicy implements RejectedExecutionHandler
+{
+   @Override
+   public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor)
+   {
+      try
+      {
+         executor.getQueue().put(runnable);
+      }
+      catch (InterruptedException interruptedException)
+      {
+         Thread.currentThread().interrupt();
+      }
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f2985d50/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/ConcurrencyBugTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/ConcurrencyBugTest.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/ConcurrencyBugTest.java
new file mode 100644
index 0000000..a931768
--- /dev/null
+++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/ConcurrencyBugTest.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.deltaspike.test.core.api.partialbean.uc012;
+
+import org.apache.deltaspike.test.core.api.partialbean.util.ArchiveUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+@RunWith(Arquillian.class)
+public class ConcurrencyBugTest
+{
+
+   @Deployment
+   public static WebArchive war()
+   {
+      final String simpleName = ConcurrencyBugTest.class.getSimpleName();
+      final String archiveName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
+
+      final JavaArchive testJar = ShrinkWrap.create(JavaArchive.class, archiveName + ".jar")
+            .addPackage(ConcurrencyBugTest.class.getPackage())
+            .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+      final WebArchive webArchive =  ShrinkWrap.create(WebArchive.class, archiveName + ".war")
+            .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreAndPartialBeanArchive())
+            .addAsLibraries(testJar)
+            .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
+
+      return webArchive;
+   }
+
+   @Inject
+   private PartialBean bean;
+
+   @Test
+   public void testWithConcurrency() throws Exception
+   {
+      ThreadFactory threadFactory = Executors.defaultThreadFactory();
+      ExecutorService executor = new ThreadPoolExecutor(5, 10, 60, SECONDS, new SynchronousQueue<Runnable>(),
+            threadFactory, new BlockPolicy());
+      int iterations = 100;
+      List<Future<String>> results = new ArrayList<Future<String>>(iterations);
+      for (int i = 0; i < iterations; i++) {
+         results.add(executor.submit(new BeanCaller(bean)));
+      }
+      executor.shutdown();
+      executor.awaitTermination(60, SECONDS);
+      for (int i = 0; i < iterations; i++)
+      {
+         results.get(i).get();
+      }
+   }
+
+   private class BeanCaller implements Callable<String>
+   {
+      private final PartialBean partialBean;
+
+      private BeanCaller(PartialBean partialBean) {
+         this.partialBean = partialBean;
+      }
+
+      @Override
+      public String call() {
+         try {
+            return partialBean.getValue();
+         }
+         catch (NullPointerException e)
+         {
+            e.printStackTrace();
+            throw e;
+         }
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f2985d50/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanBinding.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanBinding.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanBinding.java
new file mode 100644
index 0000000..1f73a27
--- /dev/null
+++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanBinding.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.deltaspike.test.core.api.partialbean.uc012;
+
+import org.apache.deltaspike.partialbean.api.PartialBeanBinding;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@PartialBeanBinding
+@Retention(RUNTIME)
+public @interface MyPartialBeanBinding
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f2985d50/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanHandler.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanHandler.java
new file mode 100644
index 0000000..fdd11c1
--- /dev/null
+++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/MyPartialBeanHandler.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.deltaspike.test.core.api.partialbean.uc012;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+@MyPartialBeanBinding
+public class MyPartialBeanHandler implements InvocationHandler
+{
+   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+   {
+      return method.getName();
+   }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f2985d50/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/PartialBean.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/PartialBean.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/PartialBean.java
new file mode 100644
index 0000000..7a6f3ea
--- /dev/null
+++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc012/PartialBean.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.deltaspike.test.core.api.partialbean.uc012;
+
+import javax.enterprise.context.ApplicationScoped;
+
+@MyPartialBeanBinding
+@ApplicationScoped
+public interface PartialBean
+{
+   String getValue();
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/f2985d50/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java
index 92bfc3c..03fcbd2 100644
--- a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java
+++ b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java
@@ -18,22 +18,20 @@
  */
 package org.apache.deltaspike.proxy.impl.invocation;
 
+import javax.enterprise.inject.spi.Interceptor;
+import javax.inject.Inject;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.util.List;
-import javax.enterprise.inject.spi.Interceptor;
-import org.apache.deltaspike.core.api.provider.BeanProvider;
 
 public abstract class AbstractManualInvocationHandler implements InvocationHandler
 {
-    private volatile Boolean initialized;
+    @Inject
     private InterceptorLookup interceptorLookup;
-    
+
     @Override
     public Object invoke(Object proxy, Method method, Object[] parameters) throws Throwable
     {
-        lazyInit();
-
         // check if interceptors are defined, otherwise just call the original logik
         List<Interceptor<?>> interceptors = interceptorLookup.lookup(proxy, method);
         if (interceptors != null && !interceptors.isEmpty())
@@ -41,7 +39,7 @@ public abstract class AbstractManualInvocationHandler implements InvocationHandl
             try
             {
                 ManualInvocationContext invocationContext =
-                        new ManualInvocationContext(this, interceptors, proxy, method, parameters, null);
+                      new ManualInvocationContext(this, interceptors, proxy, method, parameters, null);
 
                 Object returnValue = invocationContext.proceed();
 
@@ -63,33 +61,12 @@ public abstract class AbstractManualInvocationHandler implements InvocationHandl
 
     /**
      * Calls the original logic after invoking the interceptor chain.
-     * 
+     *
      * @param proxy The current proxy instance.
      * @param method The current invoked method.
      * @param parameters The method parameter.
      * @return The original value from the original method.
-     * @throws Throwable 
+     * @throws Throwable
      */
     protected abstract Object proceedOriginal(Object proxy, Method method, Object[] parameters) throws Throwable;
-
-    
-    
-    private void lazyInit()
-    {
-        if (this.initialized == null)
-        {
-            init();
-        }
-    }
-
-    private synchronized void init()
-    {
-        // switch into paranoia mode
-        if (this.initialized == null)
-        {
-            this.initialized = true;
-            
-            this.interceptorLookup = BeanProvider.getContextualReference(InterceptorLookup.class);
-        }
-    }
 }