[[events]]

== Events

Beans may produce and consume events.
This facility allows beans to interact in a completely decoupled fashion, with no compile-time dependency between the interacting beans.
Most importantly, it allows stateful beans in one architectural tier of the application to synchronize their internal state with state changes that occur in a different tier.

An event comprises:

* A Java object - the _event object_
* A set of instances of qualifier types - the _event qualifiers_


The event object acts as a payload, to propagate state from producer to consumer.
The event qualifiers act as topic selectors, allowing the consumer to narrow the set of events it observes.

An _observer method_ acts as event consumer, observing events of a specific type - the _observed event type_  - with a specific set of qualifiers - the _observed event qualifiers_.
An observer method will be notified of an event if the event object is assignable to the observed event type, and if the set of observed event qualifiers is a subset of all the event qualifiers of the event.


[[event_types_and_qualifier_types]]

=== Event types and qualifier types

An event object is an instance of a concrete Java class with no unresolvable type variables.
The _event types_ of the event include all superclasses and interfaces of the runtime class of the event object.

An event type may not contain an unresolvable type variable. A wildcard type is not considered an unresolvable type variable.

An event qualifier type is just an ordinary qualifier type as specified in <<defining_qualifier_types>>, typically defined as `@Target({METHOD, FIELD, PARAMETER, TYPE})` or `@Target({FIELD, PARAMETER})`.

Every event has the qualifier `@javax.enterprise.inject.Any`, even if it does not explicitly declare this qualifier.

Any Java type may be an observed event type.

[[firing_events]]

=== Firing events

Beans fire events via an instance of the `javax.enterprise.event.Event` interface, which may be injected:

[source, java]
----
@Inject Event<LoggedInEvent> loggedInEvent;
----

Any combination of qualifiers may be specified at the injection point:

[source, java]
----
@Inject @Admin Event<LoggedInEvent> adminLoggedInEvent;
----

Or the application may specify qualifiers dynamically:

[source, java]
----
@Inject Event<LoggedInEvent> loggedInEvent;
...
LoggedInEvent event = new LoggedInEvent(user);
if ( user.isAdmin() ) {
    loggedInEvent.select( new AdminQualifier() ).fire(event);
}
else {
    loggedInEvent.fire(event);
    loggedInEvent.fireAsync(event);
}
----

In this example, the event sometimes has the qualifier `@Admin`, depending upon the value of `user.isAdmin()`.
It is first fired synchronously with `fire()` then asynchronously with `fireAsync()`.

[[firing_events_synchronously]]

==== Firing events synchronously

The method `fire()` accepts an event object:

[source, java]
----
public void login() {
    ...
    loggedInEvent.fire( new LoggedInEvent(user) );
}
----

Event fired with the `fire()` method is fired synchronously.
All the resolved synchronous observers (as defined in <<observer_resolution>>) are called in the thread in which `fire()` was called.
A synchronous observer notification blocks the calling thread until it completes.

[[firing_events_asynchronously]]

==== Firing events asynchronously

Events may also be fired asynchronously using one of the methods `fireAsync()`

[source, java]
----
@Inject Event<LoggedInEvent> loggedInEvent;

public void login() {
    ...
    loggedInEvent.fireAsync( new LoggedInEvent(user) );
}
----

Event fired with the `fireAsync()` method is fired asynchronously.
All the resolved asynchronous observers (as defined in <<observer_resolution>>) are called in one or more different threads.

Method `fireAsync()` returns immediately.

[[event]]

==== The `Event` interface

The `Event` interface provides a method for firing events with a specified combination of type and qualifiers:

[source, java]
----
public interface Event<T> {

    public void fire(T event);
    public <U extends T> CompletionStage<U> fireAsync(U event);
    public <U extends T> CompletionStage<U> fireAsync(U event, NotificationOptions options);

    public Event<T> select(Annotation... qualifiers);
    public <U extends T> Event<U> select(Class<U> subtype, Annotation... qualifiers);
    public <U extends T> Event<U> select(TypeLiteral<U> subtype, Annotation... qualifiers);

}
----

For an injected `Event`:

* the _specified type_ is the type parameter specified at the injection point, and
* the _specified qualifiers_ are the qualifiers specified at the injection point.


For example, this injected `Event` has specified type `LoggedInEvent`:

[source, java]
----
@Inject Event<LoggedInEvent> any;
----

The `select()` method returns a child `Event` for a given specified type and additional specified qualifiers.
If no specified type is given, the specified type is the same as the parent.

For example, this child `Event` has required type `AdminLoggedInEvent` and additional specified qualifier `@Admin`:

[source, java]
----
Event<AdminLoggedInEvent> admin = any.select(
            AdminLoggedInEvent.class,
            new AdminQualifier() );
----

If the specified type contains a type variable, an `IllegalArgumentException` is thrown.

If two instances of the same non repeating qualifier type are passed to `select()`, an `IllegalArgumentException` is thrown.

If an instance of an annotation that is not a qualifier type is passed to `select()`, an `IllegalArgumentException` is thrown.

The methods `fire()` and `fireAsync()` fire an event with the specified qualifiers and notify observers, as defined by <<observer_notification>>.
If the container is unable to resolve the parameterized type of the event object, it uses the specified type to infer the parameterized type of the event types.

The method `fireAsync()` may be called with a `NotificationOptions` object to configure the observer methods notification, e.g. to specify an `Executor` object to be used for asynchronous delivery.
The container is permitted to define other non-portable notification options.

The following elements are container specific:

* the default `Executor` used by the container when `fireAsync()` is called without specifying an `Executor`,
* the `CompletionStage` returned by `fireAsync` methods, and
* all dependent stages of this initial CompletionStage.

If the runtime type of the event object contains an unresolvable type variable, an `IllegalArgumentException` is thrown.

If the runtime type of the event object is assignable to the type of a container lifecycle event, an `IllegalArgumentException` is thrown.

[[builtin_event]]

==== The built-in `Event`

The container must provide a built-in bean with:

* `Event<X>` in its set of bean types, for every Java type `X` that does not contain a type variable,
* every event qualifier type in its set of qualifier types,
* scope `@Dependent`,
* no bean name, and
* an implementation provided automatically by the container.


If an injection point of raw type `Event` is defined, the container automatically detects the problem and treats it as a definition error.

The built-in implementation must be a passivation capable dependency, as defined in <<passivation_capable_dependency>>.

[[observer_resolution]]

=== Observer resolution

The process of matching an event to its observer methods is called _observer resolution_.
The container considers event type and qualifiers when resolving observers.

Observer resolution usually occurs at runtime.

An event is delivered to an observer method if:

* The observer method belongs to an enabled bean.
* An event type is assignable to the observed event type, taking type parameters into consideration.
* The observer method has no event qualifiers or has a subset of the event qualifiers.
An observer method has an event qualifier if it has an observed event qualifier with (a) the same type and (b) the same annotation member value for each member which is not annotated `@javax.enterprise.util.Nonbinding`.
* Either the event is not a container lifecycle event, as defined in <<init_events>>, or the observer method belongs to an extension.
* The event is fired synchronously and the observer is a synchronous observer as defined in <<observes>>.
* The event is fired asynchronously and the observer is an asynchronous observer as defined in <<observes>>.


If the runtime type of the event object contains an unresolvable type variable, the container must throw an `IllegalArgumentException`.

For a custom implementation of the `ObserverMethod` interface defined in <<observer_method>>, the container must call `getObservedType()` and `getObservedQualifiers()` to determine the observed event type and qualifiers, and `isAsync()` to determine whether the observer is asynchronous or synchronous.

[[observers_assignability]]

==== Assignability of type variables, raw and parameterized types

An event type is considered assignable to a type variable if the event type is assignable to the upper bound, if any.

A parameterized event type is considered assignable to a raw observed event type if the raw types are identical.

A parameterized event type is considered assignable to a parameterized observed event type if they have identical raw type and for each parameter:

* the observed event type parameter is an actual type with identical raw type to the event type parameter, and, if the type is parameterized, the event type parameter is assignable to the observed event type parameter according to these rules, or
* the observed event type parameter is a wildcard and the event type parameter is assignable to the upper bound, if any, of the wildcard and assignable from the lower bound, if any, of the wildcard, or
* the observed event type parameter is a type variable and the event type parameter is assignable to the upper bound, if any, of the type variable.

[[event_qualifier_types_with_members]]

==== Event qualifier types with members

As usual, the qualifier type may have annotation members:

[source, java]
----
@Qualifier
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Role {
    String value();
}
----

Consider the following event:

[source, java]
----
@Inject Event<LoggedInEvent> loggedInEvent;
...
public void login() {
    final User user = ...;
    loggedInEvent.select(new RoleQualifier() { public String value() { return user.getRole(); } }).fire(new LoggedInEvent(user));
}
----

Where `RoleQualifier` is an implementation of the qualifier type `Role`:

[source, java]
----
public abstract class RoleQualifier
        extends AnnotationLiteral<Role>
        implements Role {}
----

Then the following observer method will always be notified of the event:

[source, java]
----
public void afterLogin(@Observes LoggedInEvent event) { ... }
----

Whereas this observer method may or may not be notified, depending upon the value of `user.getRole()`:

[source, java]
----
public void afterAdminLogin(@Observes @Role("admin") LoggedInEvent event) { ... }
----

As usual, the container uses `equals()` to compare event qualifier type member values.

[[multiple_event_qualifiers]]

==== Multiple event qualifiers

An event parameter may have multiple qualifiers.

[source, java]
----
public void afterDocumentUpdatedByAdmin(@Observes @Updated @ByAdmin Document doc) { ... }
----

Then this observer method will be notified if the set of observer qualifiers is a subset of the fired event's qualifiers or an empty set:

[source, java]
----
@Inject Event<Document> documentEvent;
...
documentEvent.select(new UpdatedQualifier(), new ByAdminQualifier(), new ClarificationQualifier()).fire(document);
----

In the above example the event is fired with `@ByAdmin`, `@Updated`, and `@Clarification` qualifiers. The observer qualifiers are `@Updated` and `@ByAdmin`.
Observer qualifiers therefore form a subset of event qualifiers and the observer will be notified.

Other, less specific, observers will also be notified of this event:

[source, java]
----
public void afterDocumentUpdated(@Observes @Updated Document doc) { ... }
----

[source, java]
----
public void afterDocumentEvent(@Observes Document doc) { ... }
----

On the other hand, following observer will not be notified as slightly different behaviour applies to observers with `@Default` qualifier:

[source, java]
----
public void afterDocumentDefaultEvent(@Observes @Default Document doc) { ... }
----

Such observer will only be notified for events having either no qualifiers or only `@Default` qualifier:

[source, java]
----
@Inject Event<Document> documentEvent;
@Inject @Default Event<Document> documentDefaultEvent;
...
documentEvent.fire(document);
documentDefaultEvent.fire(document);
----

[[observer_methods]]

=== Observer methods

An observer method allows the application to receive and respond to event notifications.

An observer method is a non-abstract method of a managed bean class or of an extension, as defined in <<init_events>>.
An observer method may be either static or non-static.

There may be arbitrarily many observer methods with the same event parameter type and qualifiers.

A bean (or extension) may declare multiple observer methods.

[[observer_method_event_parameter]]

==== Event parameter of an observer method

Each observer method must have exactly one _event parameter_, of the same type as the event type it observes.
When searching for observer methods for an event, the container considers the type and qualifiers of the event parameter.

If the event parameter does not explicitly declare any qualifier, the observer method observes events with no qualifier.

The event parameter type may contain a type variable or wildcard.

The event parameter may be an array type whose component type contains a type variable or a wildcard.

Modifications made to the event parameter in an observer method are propagated to following observers.
The container is not required to guarantee a consistent state for an event parameter modified by asynchronous observers.


[[observes]]

==== Declaring an observer method

An observer method may be declared by annotating a parameter `@javax.enterprise.event.Observes` or `@javax.enterprise.event.ObservesAsync` of a default-access, public, protected or private method.
That parameter is the event parameter.
The declared type of the parameter is the observed event type.

If `@Observes` is used the observer method is a synchronous observer method.

If `@ObservesAsync` is used the observer method is an asynchronous observer method.


[source, java]
----
public void afterLogin(@Observes LoggedInEvent event) { ... }

public void asyncAfterLogin(@ObservesAsync LoggedInEvent event) { ... }
----

If a method has more than one parameter annotated `@Observes` or `@ObservesAsync`, the container automatically detects the problem and treats it as a definition error.

If a method has a parameter annotated `@Observes` and `@ObservesAsync`, the container automatically detects the problem and treats it as a definition error.

Observed event qualifiers may be declared by annotating the event parameter:

[source, java]
----
public void afterLogin(@Observes @Admin LoggedInEvent event) { ... }
----

If an observer method is annotated `@Produces` or `@Inject` or has a parameter annotated `@Disposes`, the container automatically detects the problem and treats it as a definition error.

Interceptors and decorators may not declare observer methods.
If an interceptor or decorator has a method with a parameter annotated `@Observes` or `@ObservesAsync`, the container automatically detects the problem and treats it as a definition error.

In addition to the event parameter, observer methods may declare additional parameters, which may declare qualifiers.
These additional parameters are injection points.

[source, java]
----
public void afterLogin(@Observes LoggedInEvent event, @Manager User user, Logger log) { ... }
----

[[event_metadata]]

==== The `EventMetadata` interface

The interface `javax.enterprise.inject.spi.EventMetadata` provides access to metadata about an observed event.


[source, java]
----
public interface EventMetadata {
    public Set<Annotation> getQualifiers();
    public InjectionPoint getInjectionPoint();
    public Type getType();
}
----

* `getQualifiers()` returns the set of qualifiers with which the event was fired.
* `getInjectionPoint()` returns the `InjectionPoint` from which this event payload was fired, or `null` if it was fired from `BeanManager.fireEvent(...)`.
* `getType()` returns the type representing runtime class of the event object with type variables resolved.


The container must provide a bean with scope `@Dependent`, bean type `EventMetadata` and qualifier `@Default`, allowing observer methods to obtain information about the events they observe.

If an injection point of type `EventMetadata` and qualifier `@Default` which is not a parameter of an observer method exists, the container automatically detects the problem and treats it as a definition error.

[source, java]
----
public void afterLogin(@Observes LoggedInEvent event, EventMetadata metadata) { ... }
----

[[conditional_observer_methods]]

==== Conditional observer methods

A _conditional observer method_ is an observer method which is notified of an event only if an instance of the bean that defines the observer method already exists in the current context.

A conditional observer method may be declared by specifying `notifyObserver=IF_EXISTS`.

[source, java]
----
public void refreshOnDocumentUpdate(@Observes(notifyObserver=IF_EXISTS) @Updated Document doc) { ... }

public void asyncRefreshOnDocumentUpdate(@ObservesAsync(notifyObserver=IF_EXISTS) @Updated Document doc) { ... }
----

Beans with scope `@Dependent` may not have conditional observer methods.
If a bean with scope `@Dependent` has an observer method declared `notifyObserver=IF_EXISTS`, the container automatically detects the problem and treats it as a definition error.

The enumeration `javax.enterprise.event.Reception` identifies the possible values of `notifyObserver`:

[source, java]
----
public enum Reception { IF_EXISTS, ALWAYS }
----

[[transactional_observer_methods]]

==== Transactional observer methods

_Transactional observer methods_ are observer methods which receive event notifications during the before or after completion phase of the transaction in which the event was fired.
If no transaction is in progress when the event is fired, they are notified at the same time as other observers.

If the transaction is in progress, but `javax.transaction.Synchronization` callback cannot be registered due to the transaction being already marked for rollback or in state where `javax.transaction.Synchronization` callbacks cannot be registered, the _before completion_, _after completion_ and _after failure_ observer methods are notified at the same time as other observers, but _after_success_ observer methods get skipped.

* A _before completion_ observer method is called during the before completion phase of the transaction.
* An _after completion_ observer method is called during the after completion phase of the transaction.
* An _after success_ observer method is called during the after completion phase of the transaction, only when the transaction completes successfully.
* An _after failure_ observer method is called during the after completion phase of the transaction, only when the transaction fails.


The enumeration `javax.enterprise.event.TransactionPhase` identifies the kind of transactional observer method:

[source, java]
----
public enum TransactionPhase {
    IN_PROGRESS,
    BEFORE_COMPLETION,
    AFTER_COMPLETION,
    AFTER_FAILURE,
    AFTER_SUCCESS
}
----

A transactional observer method may be declared by specifying any value other than `IN_PROGRESS` for `during`:

[source, java]
----
void onDocumentUpdate(@Observes(during=AFTER_SUCCESS) @Updated Document doc) { ... }
----

Asynchronous observer cannot be declared transactional.

[[observer_notification]]

=== Observer notification

When an event is fired by the application, the container must:

* determine the observer methods for that event according to the rules of observer resolution defined by <<observer_resolution>>, then,
* for each observer method, either invoke the observer method immediately, or register the observer method for later invocation during the transaction completion phase, using a JTA `Synchronization`.
* honor the priority of observer methods as defined in <<observer_ordering>>.


The container calls observer methods as defined in <<observers_method_invocation>>.

* If the observer method is a transactional observer method and there is currently a JTA transaction in progress, the container calls the observer method during the appropriate transaction completion phase.
* If there is no context active for the scope to which the bean declaring the observer method belongs, then the observer method should not be called.
* Otherwise, the container calls the observer immediately.

Any observer method called before completion of a transaction may call `setRollbackOnly()` to force a transaction rollback.
An observer method may not directly initiate, commit or rollback JTA transactions.

Observer methods may throw exceptions:

* If the observer method is a transactional observer method, any exception is caught and logged by the container.
* If the observer method is asynchronous, the exception aborts processing of the observer but not of the event.
Exception management during an asynchronous event is defined in <<async_exception>>.
* Otherwise, the exception aborts processing of the event.
No other observer methods of that event will be called.
The `BeanManager.fireEvent()` or `Event.fire()` method rethrows the exception.
If the exception is a checked exception, it is wrapped and rethrown as an (unchecked) `ObserverException`.


For a custom implementation of the `ObserverMethod` interface defined in <<observer_method>>, the container must call `getTransactionPhase()` to determine if the observer method is transactional observer method, and `notify()` which accepts `javax.enterprise.inject.spi.EventContext` to invoke the method.

[[async_exception]]

==== Handling multiple exceptions thrown during an asynchronous event

If an event is asynchronous, and an exception is thrown by any of its notified observers, the `CompletionStage` returned by `fireAsync` will complete exceptionally with `java.util.concurrent.CompletionException` exception.
`CompletionException` contains all exceptions thrown by observers as suppressed exceptions.
They can be accessed as an array of `throwable` with the `getSuppressed` method.

It can be handled with one of the `CompletionStage` methods related to exceptions:

[source, java]
----
myEvent.fireAsync(anEventObject)
       .handle((ok, ex) -> {
           if (ok != null) {
               return ok;
           } else {
             for (Throwable t : ex.getSuppressed()) {
                      ...
             }
              ...
           } });
----

If no exception is thrown by observers then the resulting CompletionStage is completed normally with the event object.

[[observer_ordering]]

==== Observer ordering

Before the actual observer notification, the container determines an order in which the observer methods for a certain event are invoked.
The priority of an observer method may be declared by annotating the event parameter with `@Priority` annotation.
If a `@Priority` annotation is declared on an event parameter of an asynchronous observer method, non-portable behavior results.
If no `@Priority` annotation is specified, the default priority `javax.interceptor.Interceptor.Priority.APPLICATION + 500` is assumed.
Observers with smaller priority values are called first.

[source, java]
----
void afterLogin(@Observes @Priority(javax.interceptor.Interceptor.Priority.APPLICATION) LoggedInEvent event) { ... }
----

The order of more than one observer with the same priority is undefined and the observer methods are notified therefore in a non predictable order.


[[observer_method_invocation_context]]

==== Observer method invocation context

The transaction context and lifecycle contexts active when an observer method is invoked depend upon what kind of observer method it is.

* If the observer method is asynchronous, it is called in a new lifecycle contexts and a new transaction context.
As specified in <<builtin_contexts>>, contexts associated with built-in normal scope don't propagate across asynchronous observers.
* If the observer method is a before completion transactional observer method, it is called within the context of the transaction that is about to complete and with the same lifecycle contexts.
* Otherwise, if the observer method is any other kind of transactional observer method, it is called in an unspecified transaction context, but with the same lifecycle contexts as the transaction that just completed.
* Otherwise, the observer method is called in the same transaction context and lifecycle contexts as the invocation of `Event.fire()` or `BeanManager.fireEvent()`.


