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

Werner Keil werner.keil at gmail.com
Sat Jan 17 08:17:33 EST 2015


+1

I know JMS 2.x is just about to publish its first change via Errata/MR long
before the actual JSR for 2.1 is going to improve it further towards EE 8.
So it should not be a problem for Concurrency Utility JSR to do the same.

Werner

On Sat, Jan 17, 2015 at 1:53 PM, <cdi-dev-request at lists.jboss.org> wrote:

> Send cdi-dev mailing list submissions to
>         cdi-dev at lists.jboss.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         https://lists.jboss.org/mailman/listinfo/cdi-dev
> or, via email, send a message with subject or body 'help' to
>         cdi-dev-request at lists.jboss.org
>
> You can reach the person managing the list at
>         cdi-dev-owner at lists.jboss.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of cdi-dev digest..."
>
>
> Today's Topics:
>
>    1. Re: Building EJB-like @Asynchronous via interceptor in CDI
>       (arjan tijms)
>    2. Re: Building EJB-like @Asynchronous via interceptor in CDI
>       (Mark Struberg)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Sat, 17 Jan 2015 13:11:11 +0100
> From: arjan tijms <arjan.tijms at gmail.com>
> Subject: Re: [cdi-dev] Building EJB-like @Asynchronous via interceptor
>         in CDI
> To: Antonio Goncalves <antonio.goncalves at gmail.com>
> Cc: "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
> Message-ID:
>         <CAE=-
> AhAwfy35WkSD5JQPVRNSQtP1nLuHQ9-U8Mt15AjrJ_qnww at mail.gmail.com>
> Content-Type: text/plain; charset="utf-8"
>
> 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 listcdi-dev at lists.jboss.orghttps://
> 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 <http://www.antoniogoncalves.org> | Twitter
> > <http://twitter.com/agoncal> | LinkedIn
> > <http://www.linkedin.com/in/agoncal> | Pluralsight
> > <http://pluralsight.com/training/Authors/Details/antonio-goncalves> |
> Paris
> > JUG <http://www.parisjug.org> | Devoxx France <http://www.devoxx.fr>
> >
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL:
> http://lists.jboss.org/pipermail/cdi-dev/attachments/20150117/0b8212d3/attachment-0001.html
>
> ------------------------------
>
> Message: 2
> Date: Sat, 17 Jan 2015 12:53:04 +0000 (UTC)
> From: Mark Struberg <struberg at yahoo.de>
> Subject: Re: [cdi-dev] Building EJB-like @Asynchronous via interceptor
>         in CDI
> To: arjan tijms <arjan.tijms at gmail.com>,        Antonio Goncalves
>         <antonio.goncalves at gmail.com>
> Cc: "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
> Message-ID:
>         <
> 1515863897.2700554.1421499184135.JavaMail.yahoo at jws11122.mail.ir2.yahoo.com
> >
>
> Content-Type: text/plain; charset=UTF-8
>
> 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.
> >
> >
>
>
> ------------------------------
>
> _______________________________________________
> 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.
>
> End of cdi-dev Digest, Vol 50, Issue 35
> ***************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/cdi-dev/attachments/20150117/a5d69236/attachment-0001.html 


More information about the cdi-dev mailing list