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 is a special HK2 service that can be injected into a service or can be looked up from
a 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 might look like this:
@Inject
Topic<ImportantEvent> importantEventTopic;
The publish method of 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 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):
@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 service it is not given directly to the subscribers.
Instead there is an HK2 service called the TopicDistributionService
that is responsible for distributing messages from the producer to the subscribers.
Having the 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 decides to do!
The TopicDistributionService has a method called distributeMessage
which is responsible for sending events to subscribers. It takes the Topic that sent
the message and the message to send. The Topic contains information concerning the
Type of the Topic and all of its associated qualifiers.
HK2 provides a default implementation of TopicDistributionService
which will be described in the sections below.
The Default TopicDistributionService
In order to enable the default TopicDistributionService the
ServiceLocatorUtilities method enableTopicDistribution should be called:
public void initializeEvents(ServiceLocator locator) {
ServiceLocatorUtilities.enableTopicDistribution(locator);
}
The default TopicDistributionService is named HK2TopicDistributionService
and has a priority of 0. It is possible to enhance the behavior of the default
TopicDistributionService by adding an implementation of
TopicDistributionService with a higher priority and which injects
the default TopicDistributionService. Then the default implementation
can be delegated to by the custom enhanced TopicDistributionService.
An example of how to do this is given here.
Subscribers
In the HK2 default system subscribers are found by finding methods on services that have a
single parameter annotated with @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:
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 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 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. The default
TopicDistributionService will only distribute events
to services whose instances were created after the 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 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:
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.