-
Feature Request
-
Resolution: Duplicate
-
Major
-
None
-
1.0
-
None
Consider including asynchronous events as their were specified in one of the previous drafts.
[CDI-31] Asynchronous events
i haven't said that it is spec compliant or portable or supports every use-case. currently it only works with owb.
Gerhard, I don't think your AsyncInterceptor impl is quite correct and portable. Firstly the interceptors spec states: "Around-invoke and around-timeout interceptor methods run in the same Java thread as the associated target method.". So if there's some associated interceptor to be invoked after AsyncInterceptor this spec rule is violated. Furthermore I don't think it's legal/portable to invoke InvocationContext.proceed() in a different thread...
based on deltaspike that's available since today ( see http://os890.blogspot.com/2013/05/async-cdi.html ) -> you can customize it easily (if you need more than what's available).
AFAIK EJB asynchronous methods do not propagate transaction context (see 4.5.3 Transactions in spec). Frankly speaking I can not imagine how this (any context propagation) could work and what benefits it would bring.
As CDI 1.1 will surely have context lifecycle support there is a place for portable extensions to implement non-EJB async events (e.g. deltaspike module).
So I don't think it's necessary to define asychronous events in the spec. Nevertheless I do vote for independent execution with no context propagation.
@Mark That is an excellent point, but, it sounds like we're dismissing this prematurely without quantifying your statement.
I believe that the server could use a TaskExecutor internally and establish a thread pool to set limits on the resources consumed by something marked as @ Asynchronous. This is a fairly common pattern, and nothing out of the ordinary. I think the only thing that complicates this is scoped CDI beans.
The first possibility is we say each @Async execution is independent. This would be incredibly easy to implement, and it would be on the developer to pass any state (via the Event). Essentially, each @Async event operates in it's own transaction, request context, etc.
More in the spirit of CDI is to preserve the request context, transaction context, etc when executing an Async request. This is a fairly difficult implementation, but it's been done before with EJB, and perhaps that model could be simplified for CDI.
Lets discuss the complications that I did not take into account...
Well, if we start to add all those features to CDI then we will also end up having to do much more, thus consuming much more memory and time. There is no free lunch...
I've used the @Asynchronous workaround, which is why I began advocating this position. While it works ok for small numbers of EJBs, but EJBs aren't nearly as memory efficient as the pojo based model of CDI.
I'm advocating this position because we all know how long Java specs live for, and asynchronous dispatching and easy multithreading are going to be huge measurements of languages in the very near future. While CPU speeds will still increase going into the future, we're going to see a greater increase in core count and thread count per core.
Please correct me if I'm wrong, but I think that asynchronous events already exist in JEE: if an observer method is an EJB @Asynchronous one, it is called asynchronously right? With all potential problems outlined above of course. But at least the semantics is quite clear: there is no Session Scope and there is a fresh new Request Scope during the invocation.
Also on the note of immutability, don't box the developer in. It would be better to simply published best practices stating that events should almost always be immutable, but there may be a use case you haven't thought of.
Remember going into the future, our computers will soon have 8 16 32 or more cores. I think an additional annotation that could be used with @Obseves would be best. I ft would allow you to fire a single event and have a mix of observers (sync/async) respond.
Perhaps server implementations could specify the thread pool for handeling asynchronous events to cap the max number of simultaneous events happening on the server.
Although thinking about it this functionality does not add much that you can't already roll yourself with an EJB and an @Asynchronous method.
Well, but the ASYNC_NOWAIT use case is of almost no use as explained above!
I think that this could be as simple as Event.fireAsync() and BeanManager.fireAsyncEvent().
The events observers would still be notified synchronously in respect to each other (i.e. in the same thread), but fireAsync would return immediately. The async event would have its own request context, in much the same way as an async EJB invocation.
The main reason why I am against specifying the threading type on the observer is that it means that if a 3rd party adds an async observer to an event it opens you up to some very nasty thread safety bugs if you are not using immutable events.
Well, from a design perspective the current event is more like a method invocation with targets which are unknown to the caller. Thus they are atm perfectly fine to collect data from the @Observer methods.
That might also be possible if using asynchronous events. But in that case the event object would need to support multiple concurrency (which is not defined atm). Thus we cannot simply enable this in a backward compatible fashion. We would need to add a new annotation or new member value in @Observes or with the Event<T> source / EntityManager#fire(), e.g.
public enum ObserverType {
SYNCHRONOUS,
ASYNC_WAIT,
ASYNC_NOWAIT
}
Please be aware that both async methods have implications to the environment. We would e.g. need to limit the max number of Event-threads to spawn, otherwise we will quickly kill our Server.
But don't expect wonders! I'd say that in 99% of the cases the overhead to start and manage those threads is bigger than the costs of invoking all events synchronously...
ASYNC_NOWAIT (similar to @Asynchronous EJBs) is btw pretty dangerous as it is NOT relyable, must not share Session and Request Contexts, etc!
I'd love to see this in the next version of CDI. Async events would be a huge benefit to applications where async functionality is needed but JMS is overkill.
This ticket has been superseded by
CDI-499.