Xavier, I just pushed up a fix. Can you check out, rebuild and see if it fixes the issue for you? The error was pretty quick to reproduce with your test.
John On Wed, Jul 13, 2016 at 11:25 AM John D. Ament <[email protected]> wrote: > Thanks, I put in https://issues.apache.org/jira/browse/DELTASPIKE-1183 > > I'll port your test over to create a reproducible test as a part of this. > Thanks for not using data in the test, since yes the issue is in partial > bean/proxy. > > John > > > On Wed, Jul 13, 2016 at 11:20 AM Xavier Dury <[email protected]> wrote: > >> Here is a reproducible test (I am using ApplicationComposer from TomEE), >> I replaced the repository by some other partial bean to simplify. >> >> import static java.lang.annotation.RetentionPolicy.RUNTIME; >> import static java.util.concurrent.TimeUnit.SECONDS; >> >> import java.lang.annotation.Retention; >> import java.lang.reflect.InvocationHandler; >> import java.lang.reflect.Method; >> import java.util.ArrayList; >> import java.util.List; >> import java.util.concurrent.ExecutorService; >> import java.util.concurrent.Future; >> import java.util.concurrent.RejectedExecutionHandler; >> import java.util.concurrent.SynchronousQueue; >> import java.util.concurrent.ThreadPoolExecutor; >> >> import javax.annotation.Resource; >> import javax.enterprise.concurrent.ManagedThreadFactory; >> import javax.inject.Inject; >> >> import org.apache.deltaspike.core.api.provider.BeanManagerProvider; >> import org.apache.deltaspike.partialbean.api.PartialBeanBinding; >> import org.apache.deltaspike.partialbean.impl.PartialBeanBindingExtension; >> import >> org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler; >> import org.apache.deltaspike.proxy.impl.invocation.InterceptorLookup; >> import org.apache.openejb.junit.ApplicationComposerRule; >> import org.apache.openejb.testing.CdiExtensions; >> import org.apache.openejb.testing.Module; >> import org.junit.Rule; >> import org.junit.Test; >> import org.junit.rules.TestRule; >> >> public @CdiExtensions({BeanManagerProvider.class, >> PartialBeanBindingExtension.class}) class ConcurrencyBugTest { >> >> public final @Rule TestRule composer = new >> ApplicationComposerRule(this); >> >> public @PartialBeanBinding @Retention(RUNTIME) @interface >> MyPartialBeanBinding { >> } >> >> public @MyPartialBeanBinding interface PartialBean { >> >> String getValue(); >> } >> >> public static @MyPartialBeanBinding class MyPartialBeanHandler >> implements InvocationHandler { >> >> public Object invoke(Object proxy, Method method, Object[] args) >> throws Throwable { >> return method.getName(); >> } >> } >> >> private class BlockPolicy implements RejectedExecutionHandler { >> >> public @Override void rejectedExecution(Runnable runnable, >> ThreadPoolExecutor executor) { >> try { >> executor.getQueue().put(runnable); >> } catch (InterruptedException interruptedException) { >> Thread.currentThread().interrupt(); >> } >> } >> } >> >> public @Module Class<?>[] classes() { >> return new Class<?>[] { DelegateManualInvocationHandler.class, >> InterceptorLookup.class, PartialBean.class, MyPartialBeanHandler.class, >> MyPartialBeanHandler.class }; >> } >> >> private @Resource ManagedThreadFactory threadFactory; >> private @Inject PartialBean bean; >> >> public @Test void test() throws Exception { >> ExecutorService executor = new ThreadPoolExecutor(5, 10, 60, >> SECONDS, new SynchronousQueue<>(), this.threadFactory, new BlockPolicy()); >> List<Future<String>> results = new ArrayList<>(100); >> for (int i = 0; i < 100; i++) { >> results.add(executor.submit(this.bean::getValue)); >> } >> executor.shutdown(); >> executor.awaitTermination(60, SECONDS); >> for (int i = 0; i < 100; i++) { >> results.get(i).get(); >> } >> } >> } >> >> >> java.util.concurrent.ExecutionException: java.lang.NullPointerException >> at java.util.concurrent.FutureTask.report(Unknown Source) >> at java.util.concurrent.FutureTask.get(Unknown Source) >> at >> be.fgov.sfpd.attestation.ConcurrencyBugTest.test(ConcurrencyBugTest.java:79) >> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >> at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) >> at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) >> at java.lang.reflect.Method.invoke(Unknown Source) >> at >> org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) >> at >> org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) >> at >> org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) >> at >> org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) >> at >> org.apache.openejb.junit.DeployApplication$1.call(DeployApplication.java:44) >> at >> org.apache.openejb.junit.DeployApplication$1.call(DeployApplication.java:40) >> at >> org.apache.openejb.testing.ApplicationComposers.evaluate(ApplicationComposers.java:1067) >> at >> org.apache.openejb.junit.DeployApplication.evaluate(DeployApplication.java:40) >> at org.junit.rules.RunRules.evaluate(RunRules.java:20) >> at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) >> at >> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) >> at >> org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) >> at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) >> at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) >> at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) >> at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) >> at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) >> at org.junit.runners.ParentRunner.run(ParentRunner.java:363) >> at >> org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) >> at >> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) >> at >> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) >> at >> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) >> at >> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) >> at >> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) >> Caused by: java.lang.NullPointerException >> at >> org.apache.deltaspike.proxy.impl.invocation.AbstractManualInvocationHandler.invoke(AbstractManualInvocationHandler.java:38) >> at >> org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler$$OwbNormalScopeProxy0.invoke(org/apache/deltaspike/proxy/impl/invocation/DelegateManualInvocationHandler.java) >> at >> org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler.staticInvoke(DelegateManualInvocationHandler.java:40) >> at >> be.fgov.sfpd.attestation.ConcurrencyBugTest$PartialBean$$DSPartialBeanProxy.getValue(Unknown >> Source) >> at java.util.concurrent.FutureTask.run(Unknown Source) >> at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) >> at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) >> at java.lang.Thread.run(Unknown Source) >> >> ---------------------------------------- >> > From: [email protected] >> > To: [email protected] >> > Subject: RE: NPE in AbstractManualInvocationHandler >> > Date: Wed, 13 Jul 2016 16:54:20 +0200 >> > >> > I can reproduce the problem in a test (~4 times out of 5) with my whole >> application, if needed I can try to isolate the problem by reducing my app >> to the bare minimum. >> > I am using your snapshots but, if needed, I can build it myself. >> > >> > Xavier >> > >> > ---------------------------------------- >> >> From: [email protected] >> >> Date: Wed, 13 Jul 2016 14:46:29 +0000 >> >> Subject: Re: NPE in AbstractManualInvocationHandler >> >> To: [email protected] >> >> >> >> Do you have a reproducible sequence or is it only under load? I think I >> >> know the issue. Also did you build 1.7.1 yourself or pointing to our >> >> snapshots? >> >> >> >> John >> >> >> >> On Wed, Jul 13, 2016 at 10:41 AM Xavier Dury <[email protected]> >> wrote: >> >> >> >>> Sorry, >> >>> >> >>> I spoke too soon, I still have the problem: >> >>> >> >>> Caused by: java.lang.NullPointerException >> >>> at >> >>> >> org.apache.deltaspike.proxy.impl.invocation.AbstractManualInvocationHandler.invoke(AbstractManualInvocationHandler.java:38) >> >>> at >> >>> >> org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler$$OwbNormalScopeProxy0.invoke(org/apache/deltaspike/proxy/impl/invocation/DelegateManualInvocationHandler.java) >> >>> at >> >>> >> org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler.staticInvoke(DelegateManualInvocationHandler.java:40) >> >>> >> >>> Xavier >> >>> >> >>> ---------------------------------------- >> >>>> From: [email protected] >> >>>> To: [email protected] >> >>>> Subject: RE: NPE in AbstractManualInvocationHandler >> >>>> Date: Wed, 13 Jul 2016 16:36:18 +0200 >> >>>> >> >>>> Hi, >> >>>> >> >>>> Indeed, 1.7.1-SNAPSHOT fixed my problem. >> >>>> >> >>>> Thanks, >> >>>> >> >>>> Xavier >> >>>> ---------------------------------------- >> >>>>> From: [email protected] >> >>>>> Date: Wed, 13 Jul 2016 14:23:43 +0000 >> >>>>> Subject: Re: NPE in AbstractManualInvocationHandler >> >>>>> To: [email protected] >> >>>>> >> >>>>> Hi Xavier, >> >>>>> >> >>>>> Could you try with 1.7.1-snapshot? There was some weird static logic >> >>> doing >> >>>>> initialization which has been changed in the up coming 1.7.1 >> >>>>> >> >>>>> John >> >>>>> >> >>>>> On Wed, Jul 13, 2016 at 9:49 AM Xavier Dury <[email protected]> >> wrote: >> >>>>> >> >>>>>> Hi, >> >>>>>> >> >>>>>> Since I upgraded to DeltaSpike 1.7.0 / TomEE 7.0.1, I get NPEs when >> >>>>>> calling some repositories in a multi-threaded batch. >> >>>>>> >> >>>>>> Caused by: java.lang.NullPointerException >> >>>>>> at >> >>>>>> >> >>> >> org.apache.deltaspike.proxy.impl.invocation.AbstractManualInvocationHandler.invoke(AbstractManualInvocationHandler.java:40) >> >>>>>> at >> >>>>>> >> >>> >> org.apache.deltaspike.proxy.impl.invocation.DelegateManualInvocationHandler.staticInvoke(DelegateManualInvocationHandler.java:39) >> >>>>>> >> >>>>>> That line contains the following code: >> >>>>>> >> >>>>>> List<Interceptor<?>> interceptors = interceptorLookup.lookup(proxy, >> >>>>>> method); >> >>>>>> >> >>>>>> So it seems that interceptorLookup was not initialized correctly. >> >>>>>> >> >>>>>> I see there is a double-check locking on a volatile Boolean for >> >>>>>> initialization in that class... Wouldn't it be better if the >> locking >> >>>>>> occurred on the interceptorLookup or if the interceptorLookup would >> >>> also be >> >>>>>> declared as volatile? >> >>>>>> >> >>>>>> Regards, >> >>>>>> >> >>>>>> Xavier >> >>>>>> >> >>>> >> >>> >> > >> > >
