<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body 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>
<br>
<a class="moz-txt-link-freetext" href="https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/interceptors/thread/async/AsyncInterceptor.java">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<br>
<br>
<div class="moz-cite-prefix">On 01/16/2015 06:17 PM, arjan tijms
wrote:<br>
</div>
<blockquote
cite="mid:CAE=-AhDAWJX4uf-MsqySTLT+6KX00OKBCFNsoWwjJPcXX-RvrA@mail.gmail.com"
type="cite">
<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 class="mimeAttachmentHeader"></fieldset>
<br>
<pre wrap="">_______________________________________________
cdi-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:cdi-dev@lists.jboss.org">cdi-dev@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/cdi-dev">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 class="moz-txt-link-freetext" href="http://www.apache.org/licenses/LICENSE-2.0.html">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>
</body>
</html>