<p dir="ltr">+1</p>
<div class="gmail_quote">Le 18 janv. 2015 18:38, &quot;arjan tijms&quot; &lt;<a href="mailto:arjan.tijms@gmail.com">arjan.tijms@gmail.com</a>&gt; a écrit :<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi<br><br>On Sat, Jan 17, 2015 at 11:05 AM, Arne Limburg &lt;<a href="mailto:arne.limburg@openknowledge.de" target="_blank">arne.limburg@openknowledge.de</a>&gt; wrote:<br>&gt; Since we almost don’t use ThreadLocals in OWB, I guess, this should work out<br>&gt; of the box.<br>&gt; Did a quick check of the interceptor code and see no issues with handling<br>&gt; over the InvocationContext to another thread. However, the InvocationContext<br>&gt; has some internal state that could get confused, if proceed() is called in<br>&gt; parallel from two different threads, but that’s another thing. Just give it<br>&gt; a try and tell us about the result :-)<div><br></div><div>I tested it on a OWB 1.5.0-SNAPSHOT from a few weeks back as part of TomEE-2.0-SNAPSHOT and using a simple example with a request scoped bean and no other interceptors it indeed worked out of the box :) Still have to test with some more complicated setups, but things look promising.<br></div><div><br></div><div>I wonder, should anything still be spec&#39;ed for this? Perhaps just a mention somewhere that this is indeed allowed, along with a TCK test?</div><div><br></div><div>Kind regards,</div><div>Arjan</div><div><br></div><div><br></div><div><br></div><div><br>&gt;<br>&gt; Cheers,<br>&gt; Arne<br>&gt;<br>&gt; Von: arjan tijms &lt;<a href="mailto:arjan.tijms@gmail.com" target="_blank">arjan.tijms@gmail.com</a>&gt;<br>&gt; Datum: Samstag, 17. Januar 2015 00:32<br>&gt; An: Jozef Hartinger &lt;<a href="mailto:jharting@redhat.com" target="_blank">jharting@redhat.com</a>&gt;<br>&gt; Cc: &quot;<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>&quot; &lt;<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>&gt;<br>&gt; Betreff: Re: [cdi-dev] Building EJB-like @Asynchronous via interceptor in<br>&gt; CDI<br>&gt;<br>&gt; Hi,<br>&gt;<br>&gt; On Fri, Jan 16, 2015 at 10:41 PM, Jozef Hartinger &lt;<a href="mailto:jharting@redhat.com" target="_blank">jharting@redhat.com</a>&gt;<br>&gt; wrote:<br>&gt;&gt;<br>&gt;&gt; Hi Arjan,<br>&gt;&gt;<br>&gt;&gt; I did some changes recently in Weld interceptors and this usecase now<br>&gt;&gt; works smoothly. The code is not part of a release yet. See this test for a<br>&gt;&gt; simple implementation of an @Async interceptor (basically the same as your<br>&gt;&gt; initial attempt). Note that the chain is repeatable but at the same time it<br>&gt;&gt; is not reset after dispatch to a different thread so you no longer need the<br>&gt;&gt; ThreadLocal nor any other workaround.<br>&gt;<br>&gt;<br>&gt; That&#39;s quite a coincidence, it&#39;s indeed rather similar ;)<br>&gt;<br>&gt; I wonder how it now works though, as the InvocationContext &quot;ctx&quot; does not<br>&gt; seem to be made aware that it&#39;s been dispatched to a different thread from<br>&gt; within the code. Does it use an internal thread local to keep state or so?<br>&gt;<br>&gt; I&#39;ll also try to see what this does on OWB. Do you think this is something<br>&gt; that should work, or just something that Weld happens to support regardless<br>&gt; of the spec?<br>&gt;<br>&gt; Kind regards,<br>&gt; Arjan<br>&gt;<br>&gt;<br>&gt;  <br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; <a href="https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/interceptors/thread/async/AsyncInterceptor.java" target="_blank">https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/interceptors/thread/async/AsyncInterceptor.java</a><br>&gt;&gt;<br>&gt;&gt; Jozef<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; On 01/16/2015 06:17 PM, arjan tijms wrote:<br>&gt;&gt;<br>&gt;&gt; Hi,<br>&gt;&gt;<br>&gt;&gt; I&#39;m attempting to emulate EJB&#39;s @Asynchronous in CDI using interceptors.<br>&gt;&gt;<br>&gt;&gt; Originally I had defined my interceptor as follows;<br>&gt;&gt;<br>&gt;&gt; @Interceptor<br>&gt;&gt; @Asynchronous<br>&gt;&gt; @Priority(APPLICATION)<br>&gt;&gt; public class AsynchronousInterceptor implements Serializable {<br>&gt;&gt;<br>&gt;&gt;     private static final long serialVersionUID = 1L;<br>&gt;&gt;    <br>&gt;&gt;     @Resource<br>&gt;&gt;     private ManagedExecutorService managedExecutorService;<br>&gt;&gt;<br>&gt;&gt;     @AroundInvoke<br>&gt;&gt;     public Object submitAsync(InvocationContext ctx) throws Exception {<br>&gt;&gt;         return new FutureDelegator(managedExecutorService.submit( ()-&gt; {<br>&gt;&gt; return ctx.proceed(); } ));<br>&gt;&gt;     }<br>&gt;&gt;<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; With FutureDelegator as follows:<br>&gt;&gt;<br>&gt;&gt; public class FutureDelegator implements Future&lt;Object&gt; {<br>&gt;&gt;    <br>&gt;&gt;     private Future&lt;?&gt; future;<br>&gt;&gt;    <br>&gt;&gt;     public FutureDelegator(Future&lt;?&gt; future) {<br>&gt;&gt;         this.future = future;<br>&gt;&gt;     }<br>&gt;&gt;<br>&gt;&gt;     @Override<br>&gt;&gt;     public Object get() throws InterruptedException, ExecutionException {<br>&gt;&gt;         AsyncResult&lt;?&gt; asyncResult = (AsyncResult&lt;?&gt;) future.get();<br>&gt;&gt;         if (asyncResult == null) {<br>&gt;&gt;             return null;<br>&gt;&gt;         }<br>&gt;&gt;        <br>&gt;&gt;         return asyncResult.get();<br>&gt;&gt;     }<br>&gt;&gt;    <br>&gt;&gt;     @Override<br>&gt;&gt;     public Object get(long timeout, TimeUnit unit) throws<br>&gt;&gt; InterruptedException,    ExecutionException, TimeoutException {<br>&gt;&gt;         AsyncResult&lt;?&gt; asyncResult = (AsyncResult&lt;?&gt;) future.get(timeout,<br>&gt;&gt; unit);<br>&gt;&gt;         if (asyncResult == null) {<br>&gt;&gt;             return null;<br>&gt;&gt;         }<br>&gt;&gt;        <br>&gt;&gt;         return asyncResult.get();<br>&gt;&gt;     }<br>&gt;&gt;    <br>&gt;&gt;     @Override<br>&gt;&gt;     public boolean cancel(boolean mayInterruptIfRunning) {<br>&gt;&gt;         return future.cancel(mayInterruptIfRunning);<br>&gt;&gt;     }<br>&gt;&gt;    <br>&gt;&gt;     @Override<br>&gt;&gt;     public boolean isCancelled() {<br>&gt;&gt;         return future.isCancelled();<br>&gt;&gt;     }<br>&gt;&gt;     @Override<br>&gt;&gt;     public boolean isDone() {<br>&gt;&gt;         return future.isDone();<br>&gt;&gt;     }<br>&gt;&gt;    <br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; This of course didn&#39;t quite work, as the InvocationContext will be reset<br>&gt;&gt; after the @AroundInvoke method returns, and an infinite intercept loop<br>&gt;&gt; results (on Weld).<br>&gt;&gt;<br>&gt;&gt; I got it to work though on Weld by using a thread local check to break<br>&gt;&gt; that loop:<br>&gt;&gt;<br>&gt;&gt; @Interceptor<br>&gt;&gt; @Asynchronous<br>&gt;&gt; @Priority(PLATFORM_BEFORE)<br>&gt;&gt; public class AsynchronousInterceptor implements Serializable {<br>&gt;&gt;<br>&gt;&gt;     private static final long serialVersionUID = 1L;<br>&gt;&gt;    <br>&gt;&gt;     @Resource<br>&gt;&gt;     private ManagedExecutorService managedExecutorService;<br>&gt;&gt;    <br>&gt;&gt;     private static final ThreadLocal&lt;Boolean&gt; asyncInvocation = new<br>&gt;&gt; ThreadLocal&lt;Boolean&gt;();<br>&gt;&gt;<br>&gt;&gt;     @AroundInvoke<br>&gt;&gt;     public synchronized Object submitAsync(InvocationContext ctx) throws<br>&gt;&gt; Exception {<br>&gt;&gt;        <br>&gt;&gt;         if (TRUE.equals(asyncInvocation.get())) {<br>&gt;&gt;             return ctx.proceed();<br>&gt;&gt;         }<br>&gt;&gt;        <br>&gt;&gt;         return new FutureDelegator(managedExecutorService.submit( ()-&gt; {<br>&gt;&gt;             try {<br>&gt;&gt;                 asyncInvocation.set(TRUE);<br>&gt;&gt;                 return ctx.proceed();<br>&gt;&gt;             } finally {<br>&gt;&gt;                  asyncInvocation.remove();<br>&gt;&gt;             }<br>&gt;&gt;         }));<br>&gt;&gt;     }<br>&gt;&gt;<br>&gt;&gt; }<br>&gt;&gt;<br>&gt;&gt; But I&#39;ve got a feeling this works just by chance and not because the<br>&gt;&gt; workaround is so clever.<br>&gt;&gt;<br>&gt;&gt; What do you guys think, what would be the best way to support this with<br>&gt;&gt; the current CDI version? Or would CDI/Interceptors need something like<br>&gt;&gt; Servlet&#39;s async support, where the InvocationContext is put into async mode<br>&gt;&gt; whereafter it &quot;simply&quot; allows an other thread to continue processing on it?<br>&gt;&gt;<br>&gt;&gt; Kind regards,<br>&gt;&gt; Arjan Tijms<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; _______________________________________________<br>&gt;&gt; cdi-dev mailing list<br>&gt;&gt; cdi-dev@lists.jboss.orghttps://<a href="http://lists.jboss.org/mailman/listinfo/cdi-dev" target="_blank">lists.jboss.org/mailman/listinfo/cdi-dev</a><br>&gt;&gt;<br>&gt;&gt; Note that for all code provided on this list, the provider licenses the<br>&gt;&gt; code under the Apache License, Version 2<br>&gt;&gt; (<a href="http://www.apache.org/licenses/LICENSE-2.0.html" target="_blank">http://www.apache.org/licenses/LICENSE-2.0.html</a>). For all other ideas<br>&gt;&gt; provided on this list, the provider waives all patent and other intellectual<br>&gt;&gt; property rights inherent in such information.<br>&gt;&gt;<br>&gt;&gt;<br>&gt;<br><br></div></div>
<br>_______________________________________________<br>
cdi-dev mailing list<br>
<a href="mailto:cdi-dev@lists.jboss.org">cdi-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/cdi-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/cdi-dev</a><br>
<br>
Note that for all code provided on this list, the provider licenses the code under the Apache License, Version 2 (<a href="http://www.apache.org/licenses/LICENSE-2.0.html" target="_blank">http://www.apache.org/licenses/LICENSE-2.0.html</a>). For all other ideas provided on this list, the provider waives all patent and other intellectual property rights inherent in such information.<br></blockquote></div>