<div dir="ltr">Hi,<br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 16, 2015 at 10:41 PM, Jozef Hartinger <span dir="ltr"><<a href="mailto:jharting@redhat.com" target="_blank">jharting@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div text="#000000" bgcolor="#FFFFFF">
Hi Arjan,<br>
<br>
I did some changes recently in Weld interceptors and this usecase
now works smoothly. The code is not part of a release yet. See this
test for a simple implementation of an @Async interceptor (basically
the same as your initial attempt). Note that the chain is repeatable
but at the same time it is not reset after dispatch to a different
thread so you no longer need the ThreadLocal nor any other
workaround.<br></div></blockquote><div><br></div><div>That's quite a coincidence, it's indeed rather similar ;)</div><div><br></div><div>I wonder how it now works though, as the InvocationContext "ctx" does not seem to be made aware that it's been dispatched to a different thread from within the code. Does it use an internal thread local to keep state or so?</div><div><br></div><div>I'll also try to see what this does on OWB. Do you think this is something that should work, or just something that Weld happens to support regardless of the spec?</div><div><br></div><div>Kind regards,</div><div>Arjan</div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div text="#000000" bgcolor="#FFFFFF">
<br>
<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>
<br>
Jozef<div><div class="h5"><br>
<br>
<div>On 01/16/2015 06:17 PM, arjan tijms
wrote:<br>
</div>
</div></div><blockquote type="cite"><div><div class="h5">
<div dir="ltr">
<div>
<div>Hi,<br>
<br>
</div>
I'm attempting to emulate EJB's @Asynchronous in CDI using
interceptors.<br>
<br>
Originally I had defined my interceptor as follows;<br>
<br>
@Interceptor<br>
@Asynchronous<br>
@Priority(APPLICATION)<br>
public class AsynchronousInterceptor implements Serializable {<br>
<br>
private static final long serialVersionUID = 1L;<br>
<br>
@Resource<br>
private ManagedExecutorService managedExecutorService;<br>
<br>
@AroundInvoke<br>
public Object submitAsync(InvocationContext ctx) throws
Exception {<br>
return new
FutureDelegator(managedExecutorService.submit( ()-> {
return ctx.proceed(); } ));<br>
}<br>
<br>
}<br>
<br>
</div>
<div>With FutureDelegator as follows:<br>
<br>
public class FutureDelegator implements Future<Object> {<br>
<br>
private Future<?> future;<br>
<br>
public FutureDelegator(Future<?> future) {<br>
this.future = future;<br>
}<br>
<br>
@Override<br>
public Object get() throws InterruptedException,
ExecutionException {<br>
AsyncResult<?> asyncResult =
(AsyncResult<?>) future.get();<br>
if (asyncResult == null) {<br>
return null;<br>
}<br>
<br>
return asyncResult.get(); <br>
}<br>
<br>
@Override<br>
public Object get(long timeout, TimeUnit unit) throws
InterruptedException, ExecutionException, TimeoutException
{<br>
AsyncResult<?> asyncResult =
(AsyncResult<?>) future.get(timeout, unit);<br>
if (asyncResult == null) {<br>
return null;<br>
}<br>
<br>
return asyncResult.get(); <br>
}<br>
<br>
@Override<br>
public boolean cancel(boolean mayInterruptIfRunning) {<br>
return future.cancel(mayInterruptIfRunning);<br>
}<br>
<br>
@Override<br>
public boolean isCancelled() {<br>
return future.isCancelled();<br>
}<br>
@Override<br>
public boolean isDone() {<br>
return future.isDone();<br>
}<br>
<br>
}<br>
<br>
</div>
<div>This of course didn't quite work, as the InvocationContext
will be reset after the @AroundInvoke method returns, and an
infinite intercept loop results (on Weld).<br>
<br>
I got it to work though on Weld by using a thread local check
to break that loop:<br>
<br>
@Interceptor<br>
@Asynchronous<br>
@Priority(PLATFORM_BEFORE)<br>
public class AsynchronousInterceptor implements Serializable {<br>
<br>
private static final long serialVersionUID = 1L;<br>
<br>
@Resource<br>
private ManagedExecutorService managedExecutorService;<br>
<br>
private static final ThreadLocal<Boolean>
asyncInvocation = new ThreadLocal<Boolean>();<br>
<br>
@AroundInvoke<br>
public synchronized Object submitAsync(InvocationContext
ctx) throws Exception {<br>
<br>
if (TRUE.equals(asyncInvocation.get())) {<br>
return ctx.proceed();<br>
}<br>
<br>
return new
FutureDelegator(managedExecutorService.submit( ()-> { <br>
try {<br>
asyncInvocation.set(TRUE);<br>
return ctx.proceed();<br>
} finally {<br>
asyncInvocation.remove();<br>
}<br>
}));<br>
}<br>
<br>
}<br>
<br>
</div>
<div>But I've got a feeling this works just by chance and not
because the workaround is so clever.<br>
<br>
</div>
<div>What do you guys think, what would be the best way to
support this with the current CDI version? Or would
CDI/Interceptors need something like Servlet's async support,
where the InvocationContext is put into async mode whereafter
it "simply" allows an other thread to continue processing on
it?<br>
<br>
</div>
<div>Kind regards,<br>
Arjan Tijms<br>
</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
<br>
</div>
</div>
<br>
<fieldset></fieldset>
<br>
</div></div><pre>_______________________________________________
cdi-dev mailing list
<a href="mailto:cdi-dev@lists.jboss.org" target="_blank">cdi-dev@lists.jboss.org</a>
<a href="https://lists.jboss.org/mailman/listinfo/cdi-dev" target="_blank">https://lists.jboss.org/mailman/listinfo/cdi-dev</a>
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.</pre>
</blockquote>
<br>
</div>
</blockquote></div><br></div></div>