[cdi-dev] Building EJB-like @Asynchronous via interceptor in CDI

arjan tijms arjan.tijms at gmail.com
Sat Jan 17 11:46:36 EST 2015


Hi,

On Sat, Jan 17, 2015 at 4:30 PM, Antonio Goncalves
<antonio.goncalves at gmail.com> wrote:
> So I don't know how we could "push" for an MR of the EE Concurrency spec.
> Any idea ? Except harassing Bill to add resources to the EE Concurrency spec
> and taking other resources out somewhere else... I don't know how we could
> do this.

Maybe by doing the work largely ourselves and then contributing it?
E.g. having the RI implementation done, writing a test for it, writing
some spec prose, etc. That way Anthony Lai would mainly have to
formally accept that work. This would all be a lot easier of course if
the code, tck and documentation was all on GitHub, then it would just
be 3 pull requests ;)

Kind regards,
Arjan


>
> @Mark EE Concurreny could also add a @ThreadScoped like the one in Weld (but
> with a EE meaning).
>
> Antonio
>
>
> On Sat, Jan 17, 2015 at 1:53 PM, Mark Struberg <struberg at yahoo.de> wrote:
>>
>> 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 at gmail.com>
>> wrote:
>>
>>
>> >
>> >
>> >Hi,
>> >
>> >
>> >
>> >On Sat, Jan 17, 2015 at 11:05 AM, Antonio Goncalves
>> > <antonio.goncalves at 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 at gmail.com>
>> >> wrote:
>> >>
>> >>Hi,
>> >>>
>> >>>
>> >>>
>> >>>On Fri, Jan 16, 2015 at 10:41 PM, Jozef Hartinger <jharting at 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 at 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 at 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 at 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


More information about the cdi-dev mailing list