EE concurrency spec needs an update anyway. It currently doesn't explicitly require
@RequestScoped beans to be supported on a new Thread. That breaks tons of frameworks and
makes it barely usable in EE7.
LieGrue,
strub
On Saturday, 17 January 2015, 13:12, arjan tijms <arjan.tijms(a)gmail.com> wrote:
Hi,
On Sat, Jan 17, 2015 at 11:05 AM, Antonio Goncalves <antonio.goncalves(a)gmail.com>
wrote:
@arjan Your example is base on ManagedExecutorService from the Java EE Concurrency spec.
That's one topic we've been wondering about : should the @Asynchronous interceptor
go to the Java EE Concurrency spec or not ? But it looks like the spec might not be
updated.
The example I showed here would IMHO best be placed in the Java EE Concurrency spec. That
would in my opinion be a perfect analogy to @Transactional and JTA. As given, the
interceptor uses CDI/Interceptors and Concurrency, so theoretically it could also be put
into a third spec.
Personally I would find it strange to put something in spec A, when it may better belong
in spec B, just because spec B is not updated. What's holding the update of Java EE
Concurrency back? If most of the EG members would be of the opinion that an @Asynchronous
interceptor belongs best in Java EE Concurrency, then we can just update that spec,
right?
I know that MR releases can be quite fast and agile process wise, while still packing some
punch. JTA 1.2 itself was just such an MR, and JASPIC 1.1 was too. I was somewhat involved
with JASPIC 1.1 (as community member) and I think the setup time was pretty fast. Mid feb
2013 we created the JIRA issues, the MR draft was published early march 2013 and the
release was with EE 7 end may 2013.
If it would just be about putting a few interceptors formally in Java EE Concurrency, then
why not do such small update for it?
Kind regards,
Arjan
>
>Antonio
>
>
>On Sat, Jan 17, 2015 at 12:32 AM, arjan tijms <arjan.tijms(a)gmail.com> wrote:
>
>Hi,
>>
>>
>>
>>On Fri, Jan 16, 2015 at 10:41 PM, Jozef Hartinger <jharting(a)redhat.com>
wrote:
>>
>>Hi Arjan,
>>>
>>>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.
>>>
>>
>>
>>That's quite a coincidence, it's indeed rather similar ;)
>>
>>
>>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?
>>
>>
>>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?
>>
>>
>>Kind regards,
>>Arjan
>>
>>
>>
>>
>>
>>
>>>https://github.com/weld/core/blob/master/tests-arquillian/src/test/java/org/jboss/weld/tests/interceptors/thread/async/AsyncInterceptor.java
>>>
>>>Jozef
>>>
>>>
>>>
>>>On 01/16/2015 06:17 PM, arjan tijms wrote:
>>>
>>>Hi,
>>>>
>>>>
I'm attempting to emulate EJB's @Asynchronous in CDI using
interceptors.
>>>>
>>>>Originally I had defined my interceptor as follows;
>>>>
>>>>@Interceptor
>>>>@Asynchronous
>>>>@Priority(APPLICATION)
>>>>public class AsynchronousInterceptor implements Serializable {
>>>>
>>>> private static final long serialVersionUID = 1L;
>>>>
>>>> @Resource
>>>> private ManagedExecutorService managedExecutorService;
>>>>
>>>> @AroundInvoke
>>>> public Object submitAsync(InvocationContext ctx) throws
Exception {
>>>> return new
FutureDelegator(managedExecutorService.submit( ()-> {
return ctx.proceed(); } ));
>>>> }
>>>>
>>>>}
>>>>
>>>>
>>>>With FutureDelegator as follows:
>>>>
>>>>public class FutureDelegator implements Future<Object> {
>>>>
>>>> private Future<?> future;
>>>>
>>>> public FutureDelegator(Future<?> future) {
>>>> this.future = future;
>>>> }
>>>>
>>>> @Override
>>>> public Object get() throws InterruptedException,
ExecutionException {
>>>> AsyncResult<?> asyncResult =
(AsyncResult<?>) future.get();
>>>> if (asyncResult == null) {
>>>> return null;
>>>> }
>>>>
>>>> return asyncResult.get();
>>>> }
>>>>
>>>> @Override
>>>> public Object get(long timeout, TimeUnit unit) throws
InterruptedException, ExecutionException, TimeoutException
{
>>>> AsyncResult<?> asyncResult =
(AsyncResult<?>) future.get(timeout, unit);
>>>> if (asyncResult == null) {
>>>> return null;
>>>> }
>>>>
>>>> return asyncResult.get();
>>>> }
>>>>
>>>> @Override
>>>> public boolean cancel(boolean mayInterruptIfRunning) {
>>>> return future.cancel(mayInterruptIfRunning);
>>>> }
>>>>
>>>> @Override
>>>> public boolean isCancelled() {
>>>> return future.isCancelled();
>>>> }
>>>> @Override
>>>> public boolean isDone() {
>>>> return future.isDone();
>>>> }
>>>>
>>>>}
>>>>
>>>>
>>>>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).
>>>>
>>>>I got it to work though on Weld by using a thread local check
to break that loop:
>>>>
>>>>@Interceptor
>>>>@Asynchronous
>>>>@Priority(PLATFORM_BEFORE)
>>>>public class AsynchronousInterceptor implements Serializable {
>>>>
>>>> private static final long serialVersionUID = 1L;
>>>>
>>>> @Resource
>>>> private ManagedExecutorService managedExecutorService;
>>>>
>>>> private static final ThreadLocal<Boolean>
asyncInvocation = new ThreadLocal<Boolean>();
>>>>
>>>> @AroundInvoke
>>>> public synchronized Object submitAsync(InvocationContext
ctx) throws Exception {
>>>>>
>>>>> if (TRUE.equals(asyncInvocation.get())) {
>>>>> return ctx.proceed();
>>>>> }
>>>>>
>>>> return new
FutureDelegator(managedExecutorService.submit( ()-> {
>>>> try {
>>>> asyncInvocation.set(TRUE);
>>>> return ctx.proceed();
>>>> } finally {
>>>> asyncInvocation.remove();
>>>> }
>>>> }));
>>>> }
>>>>
>>>>}
>>>>
>>>>
>>>>But I've got a feeling this works just by chance and not because the
workaround is so clever.
>>>>
>>>>
>>>>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?
>>>>
>>>>
>>>>Kind regards,
>>>>Arjan Tijms
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>_______________________________________________
cdi-dev mailing list
cdi-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/cdi-dev Note that for all
code provided on this list, the provider licenses the code under the Apache License,
Version 2 (
http://www.apache.org/licenses/LICENSE-2.0.html). For all other ideas provided
on this list, the provider waives all patent and other intellectual property rights
inherent in such information.
>>>
>>
>>_______________________________________________
>>cdi-dev mailing list
>>cdi-dev(a)lists.jboss.org
>>https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>>Note that for all code provided on this list, the provider licenses the code under
the Apache License, Version 2 (
http://www.apache.org/licenses/LICENSE-2.0.html). For all
other ideas provided on this list, the provider waives all patent and other intellectual
property rights inherent in such information.
>>
>
>
>
>--
>
>Antonio Goncalves
>Software architect, Java Champion and Pluralsight author
>
>Web site | Twitter | LinkedIn | Pluralsight | Paris JUG | Devoxx France
_______________________________________________
cdi-dev mailing list
cdi-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/cdi-dev
Note that for all code provided on this list, the provider licenses the code under the
Apache License, Version 2 (
http://www.apache.org/licenses/LICENSE-2.0.html). For all other
ideas provided on this list, the provider waives all patent and other intellectual
property rights inherent in such information.