blob: 9092f5f0083e05ad7dd3ce24d7671af8a8b4b86e [file] [log] [blame] [view] [edit]
[//]: # " "
[//]: # " Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. "
[//]: # " "
[//]: # " This program and the accompanying materials are made available under the "
[//]: # " terms of the Eclipse Public License v. 2.0, which is available at "
[//]: # " http://www.eclipse.org/legal/epl-2.0. "
[//]: # " "
[//]: # " This Source Code may also be made available under the following Secondary "
[//]: # " Licenses when the conditions for such availability set forth in the "
[//]: # " Eclipse Public License v. 2.0 are satisfied: GNU General Public License, "
[//]: # " version 2 with the GNU Classpath Exception, which is available at "
[//]: # " https://www.gnu.org/software/classpath/license.html. "
[//]: # " "
[//]: # " SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 "
[//]: # " "
* TOC
{:toc}
# Events
The HK2 event service provides a pluggable mechanism that allows delivery of messages from service to
service. Those services sending events are called publishers and those receiving events are called
subscribers. A message can be any java object.
## Topics
A [Topic][topic] is a special HK2 service that can be injected into a service or can be looked up from
a [ServiceLocator][servicelocator]. It normally is injected as a ParameterizedType, where the generic
Type is the class of the event that will be published. So if there is an event class called ImportantEvent
that is to be distributed to subscribers, the injection point for the [Topic][topic] might look like this:
```java
@Inject
Topic<ImportantEvent> importantEventTopic;
```
The publish method of [Topic][topic] will distribute the message to the set of subscribers. In this way
the subscribers and the publishers need not have any previous knowledge of each other.
A [Topic][topic] may have qualifiers associated with it. These qualifiers will normally be used to
further select the set of subscribers who should receive the message. In the following example
only those subscribers who ask for CodeRed ImportEvent events will receive them (assuming CodeRed is
a qualifier):
```java
@Inject @CodeRed
Topic<ImportantEvent> importantEventTopic;
```
## Pluggability
In order to provide maximum flexibility in terms of qualities of service between publishers and
subscribers the HK2 event subsystem is pluggable. This means that when a message is published
by the publish method of the [Topic][topic] service it is not given directly to the subscribers.
Instead there is an HK2 service called the [TopicDistributionService][topicdistributionservice]
that is responsible for distributing messages from the producer to the subscribers.
Having the [TopicDistributionService][topicdistributionservice] be responsible for the distribution
of messages allows the designers of the system to control the quality of service between the
producers and the subscribers. Some of the qualities of service that can be controlled this way are
security, threading and error handling. It is even possible to distribute events outside of the
JVM if that is what the [TopicDistributionService][topicdistributionservice] decides to do!
The [TopicDistributionService][topicdistributionservice] has a method called distributeMessage
which is responsible for sending events to subscribers. It takes the [Topic][topic] that sent
the message and the message to send. The [Topic][topic] contains information concerning the
Type of the [Topic][topic] and all of its associated qualifiers.
HK2 provides a default implementation of [TopicDistributionService][topicdistributionservice]
which will be described in the sections below.
## The Default TopicDistributionService
In order to enable the default [TopicDistributionService][topicdistributionservice] the
[ServiceLocatorUtilities][servicelocatorutilities] method enableTopicDistribution should be called:
```java
public void initializeEvents(ServiceLocator locator) {
ServiceLocatorUtilities.enableTopicDistribution(locator);
}
```
The default [TopicDistributionService][topicdistributionservice] is named HK2TopicDistributionService
and has a priority of 0. It is possible to enhance the behavior of the default
[TopicDistributionService][topicdistributionservice] by adding an implementation of
[TopicDistributionService][topicdistributionservice] with a higher priority and which injects
the default [TopicDistributionService][topicdistributionservice]. Then the default implementation
can be delegated to by the custom enhanced [TopicDistributionService][topicdistributionservice].
An example of how to do this is given [here][threaded-events-example].
## Subscribers
In the HK2 default system subscribers are found by finding methods on services that have a
single parameter annotated with [@SubscribeTo][subscribeto]. Any other parameters of the
method are considered to be injection points that should be satisfied by normal HK2 services.
The following methods are all subscribers to ImportantEvent:
```java
public void importantEventSubscriber(@SubscribeTo ImportantEvent event) {
// Do something with this important event
}
public void importantEventSubscriber(@SubscribeTo ImportantEvent event, ServiceLocator locator) {
// Do something with this important event and with the ServiceLocator
}
public void importantEventSubscriber(ServiceLocator locator, @SubscribeTo ImportantEvent event) {
// Do something with this important event and with the ServiceLocator
}
```
All three of the above methods will be called when a [Topic][topic] publish method is called with
an ImportantEvent.
In the default implementation the subscribers will be called on the same thread as the caller of
the [Topic][topic] publish method. Any exceptions thrown by subscribers (or for other reasons such
as an injection point not being available) will be given to all registered implementations of the
[DefaultTopicDistributionErrorService][defaulttopicdistributionerrorservice]. The default
[TopicDistributionService][topicdistributionservice] will only distribute events
to services whose instances were created after the [ServiceLocatorUtilities][servicelocatorutilities]
method enableTopicDistribution has been called. Any subscribers on a service that is disposed or
has had its associated descriptor removed will not be invoked.
Events will only be given to services that have already been created. For example an event will
not cause a Singleton service that has not already been instantiated to become instantiated, even if
the Singleton service is a listener to the event.
A method parameter with [@SubscribeTo][subscribeto] can also take qualifiers. A qualifier will
restrict the set of messages that will be given to the subscription method. For example the
following method will only get ImportantEvents from Topics that are also qualified with
the CodeRed qualifier:
```java
public void codeRedSubscriber(@SubscribeTo @CodeRed ImportantEvent redEvent) {
// do something with the code-red event
}
```
If an injection point on a subscription method has scope PerLookup then the instance of
that service will be disposed after the subscription method has returned.
## Conclusion
Events can help your application have low cohesion, as subscribers and publishers need not
have any relationship other than agreeing on an event Type. HK2 provides a powerful mechanism
for plugging in any messaging provider to provide desired qualities of service. A default
messaging provider is available which can either be replaced or enhanced if other qualities
of service are required by the application.
[topic]: apidocs/org/glassfish/hk2/api/messaging/Topic.html
[servicelocator]: apidocs/org/glassfish/hk2/api/ServiceLocator.html
[topicdistributionservice]: apidocs/org/glassfish/hk2/api/messaging/TopicDistributionService.html
[servicelocatorutilities]: apidocs/org/glassfish/hk2/utilities/ServiceLocatorUtilities.html
[subscribeto]: apidocs/org/glassfish/hk2/api/messaging/SubscribeTo.html
[defaulttopicdistributionerrorservice]: apidocs/org/glassfish/hk2/utilities/DefaultTopicDistributionErrorService.html
[threaded-events-example]: threaded-events-example.html