Eventing systems are a common part of software programs, used to distribute information between parts of an application. To address this, the Event Admin Service Specification was created as one of the earliest specifications defined by the OSGi Compendium. The design and usage of the Event Admin specification, however, makes certain trade-offs that do not fit well with modern application design:
-
Type Safety - Events are sent and received as opaque maps of key-value pairs. The “schema” of an event is therefore ill-defined and relies on “magic strings” being used correctly to locate data, and on careful handling of data values with unknown types.
-
Unhandled Events - Events that are sent but have no interested Event Consumers are silently discarded. There is no way to know that an event was not handled, short of disrupting the system by registering a handler for all events.
-
Observability - There is no simple, non-invasive way to monitor the flow of events through the system. The ability to monitor and profile applications using Event Admin is therefore relatively limited.
Adding these features to the original Event Admin Service Specification specification is not feasible without breaking backward compatibility for clients. Therefore this specification exists to provide an alternative eventing model which supports these different requirements by making different design trade-offs.
-
Event - A set of data created by an Event Source, encapsulated as an object and delivered to one or more Event Consumers.
-
Event Schema - A definition of the expected data layout within an event, including the names of data fields and the types of data that they contain.
-
Event Topic - A String identifying the topic of an Event, effectively defining the Event Schema and the purpose of the event.
-
Event Source - A software component which creates and sends events.
-
Event Consumer - A software component which receives events.
-
DTO - A Data Transfer Object as per the OSGi DTO Specification.
-
Event Bus - A software component used by an Event Source and responsible for delivering Events to Event Consumers.
-
Typed Event Bus - A service registered by the Typed Event implementation that can be passed an Event object and that will distribute that event to any suitable Event Handler Services.
-
Event Handler - A service registered by an Event Consumer suitable for receiving Event data from the Typed Event Bus.
In this specification an Event is a set of string keys associated with data values. The defined set of allowable keys and permitted value types for the keys in an Event is known as the Event Schema. Both the Event Source and Event Consumers must agree on a schema, or set of compatible schemas, in order for events to be consumed correctly.
A Type Safe Event is one in which the Event Schema is defined as a Java class. Using a Java class provides a formal definition of the schema - event data uses field names in the class as the keys, and each field definition defines the permitted type of the value.
Type Safe Event classes are expected to either:
-
Conform to OSGi DTO rules - the architecture of OSGi DTOs is described in OSGi Core Release 8. All methods, all static fields, and any non public instance fields of an event object must be ignored by the Typed Event Service when processing the Event data.
-
Be [1] Java Records. Event classes that are Java Records can be identified as they are subclasses of
java.lang.Record
. The Event data consists of the record components. All other parts of a record must be ignored by the Typed Event Service when processing the Event data.
Some implementations of the Typed Event Service may support Type Safe Event classes that do not conform to these rules, transforming them as needed in an implementation specific way. This is permitted by this specification, however consumers which rely on this behaviour may not be portable between different implementations of this specification.
OSGi DTOs are permitted to have data values which are also DTOs, allowing nested data structures to be created. This is also allowed for Type Safe Events, but with the same restriction that the event data must be a tree. There is no restriction on the depth of nesting permitted.
An Untyped Event is one in which there is no Java class defining
the Event Schema. In this case the event data is defined using a
Map
type with String
keys and values limited
to types acceptable as fields in a DTO, excepting:
-
DTO types - an untyped event may not have DTOs inside it as these form part of a typed schema.
-
Maps are only permitted if they follow the rules for Untyped events, that is having
String
keys and DTO restricted value types excluding DTOs.
Untyped Event instances are capable of representing exactly the same data as present in a Type Safe Event instance, and are also subject to the same restrictions, that is the data must be a tree. Nested data should be included as sub-maps within the event map, and these sub-maps may in turn contain nested data.
Some Event schemas may be represented by an existing type which does not match the rules for acceptable type safe event classes. In this case there are two main options:
-
Create a DTO or record representation of the event schema, and convert from the existing type into the new representation in code.
-
Convert the event data into an Untyped Event representation using nested Maps.
For example, the following code demonstrates how an object following the JavaBeans pattern can be converted into a DTO type or an untyped map:
public class ExampleJavaBean {
private String message;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
public class ExampleEvent {
public String message;
}
@Component
public class ExampleEventSource {
private ExampleEvent createEventFromJavaBean(ExampleJavaBean bean) {
return Converters.standardConverter().convert(bean)
.to(ExampleEvent.class);
}
private Map<String, Object> createMapFromJavaBean(ExampleJavaBean bean) {
return Converters.standardConverter().convert(bean)
.to(new TypeReference<Map<String, Object>>(){});
}
}
The Typed Event Service is inherently multi-threaded. Events may
be published from multiple threads, and event data may be delivered to
consumers on multiple threads. Event Sources and Event Consumers must
therefore assume that event data is shared between threads from the
moment that it is first passed to the TypedEventBus
.
Typed Events, and in particular DTO types, provide a simple yet powerful mechanism for defining an Event Schema in a type-safe way. However their use of mutable public fields means that they are potentially dangerous when shared between threads. Event Sources and Event Consumers should assume that their event instances are shared between threads and therefore not mutate the event data after publication or receipt.
If an Event Handler does need to make changes to an incoming event then it must copy the event data into a new DTO instance. Note that any nested DTO values in the event data must also be copied if they are to be mutated.
When an event source publishes untyped event data, it passes a Map instance to the Typed Event Bus. The Typed Event Bus is not required to take a copy of this Map, and therefore the event source must not change the Map, or any data structures within the Map, after the call to deliverUntyped(String,Map).
Untyped Events are delivered as implementations of the Map interface. Bundles consuming untyped events should not rely on the event object being any particular implementation of Map, and should treat the event object as immutable. The Typed Event Bus implementation may make copies of the event data, or enforce the immutability of the map, before passing the event data to an Event Handler.
To publish an event, the Event Source must retrieve the Typed Event Bus service from the OSGi service registry. The Event Source then creates an event object and calls one of the Typed Event Bus service's methods to publish the event. Event publication is asynchronous, meaning that when a call to the Typed Event Bus returns there is no guarantee that all, or even any, listeners have been notified.
Events are always published to a topic. The topic of an event defines the schema of the event. Topics exist in order to give Event Consumers information about the schema of the event, and the opportunity to register for just the events they are interested in. When a topic is designed, its name should not include any other information, such as the publisher of the event or the data associated with the event, those parts are intended to be stored in the event properties.
The topic therefore serves as a first-level filter for determining which handlers should receive the event. Typed Event service implementations use the structure of the topic to optimize the dispatching of the events to the handlers. The following example code demonstrates how to send an event to a topic.
public class ExampleEvent {
public String message;
}
@Component
public class ExampleEventSource {
@Reference
TypedEventBus bus;
public void sendEvent() {
ExampleEvent event = new ExampleEvent();
event.message = "The time is " + LocalDateTime.now();
bus.deliver("org/osgi/example/ExampleEvent", event);
}
}
Topics are arranged in a hierarchical namespace. Each level is
defined by a token and levels are separated by solidi ('/'
\u002F
). More precisely, the topic must conform to the following
grammar:
// For further information see General Syntax Definitions in Core
topictoken :: ( jletterordigit | '-' ) +
topic ::= topictoken ( '/' topictoken ) *
Topics should be designed to become more specific when going from left to right. Consumers can provide a prefix that matches a topic, using the preferred order allows a handler to minimize the number of prefixes it needs to register.
Topics are case-sensitive. As a convention, topics should follow
the reverse domain name scheme used by Java packages to guarantee
uniqueness. The separator must be a solidus ('/' \u002F
)
instead of the full stop ('.' \u002E
).
This specification uses the convention
fully/qualified/package/ClassName/ACTION
. If necessary, a
pseudo-class-name is used.
In many cases the name of a topic contains no information other than defining the schema of the events sent on that topic. Therefore, when publishing a Typed Event to the Typed Event Bus, the Typed Event implementation is able to automatically generate a topic name based on the the type of the event object being published.
For the deliver(Object) method on the Typed Event Bus where no topic
string is provided, the implementation must create a topic string using
the fully qualified class name of the event object. To convert the class
name into a valid topic the full stop .
separators must be
converted into solidus /
separators. A non-normative
example implementation follows:
public void deliver(Object event) {
String topicName = event.getClass().getName().replace('.', '/');
this.deliver(topicName, event);
}
The following example demonstrates how an Event Source can make use of an automatically generated topic name.
package org.osgi.example;
public class ExampleEvent {
public String message;
}
@Component
public class ExampleEventSource {
@Reference
TypedEventBus bus;
public void sendEvent() {
ExampleEvent event = new ExampleEvent();
event.message = "The time is " + LocalDateTime.now();
// This event will be delivered to the
// topic "org/osgi/example/ExampleEvent"
bus.deliver(event);
}
}
The TypedEventBus
implementation must be thread safe
and allow for simultaneous event publication from multiple threads. For
any given source thread, events must be delivered in the same order as
they were published by that thread. Events published by different
threads, however, may be delivered in a different order from the one in
which they were published.
For example, if thread A publishes events 1, 2 and 3, while thread B publishes events 4, 5 and 6, then the events may be delivered:
-
1, 2, 3, 4, 5, 6
-
4, 1, 2, 5, 6, 3
-
and so on
but events will never be delivered 1, 2, 6, 4, 5, 3
Typical Event Sources publish single events at irregular intervals.
These event sources are best served by using the deliver
methods on the TypedEventBus
. Some Event Sources, however,
produce bursts of events, or frequent, regular events to a topic. In
these cases there can be overhead associated with validating the topic
and security context each time an event is published.
A TypedEventPublisher
is associated with a single
topic which is set during creation. All events published using the
TypedEventPublisher
are delivered to that topic. A
TypedEventPublisher
can be obtained from the
TypedEventBus
using one of the createPublisher
methods.
A TypedEventPublisher
is AutoCloseable
and the isOpen
method may be used to determine whether it
has been closed. Once closed the object may no longer be used to publish
events, and all event delivery methods will throw IllegalStateException
.
public class ExampleEvent {
public String message;
}
@Component
public class ExampleEventSource {
@Reference
TypedEventBus bus;
public void sendEvents() {
try(TypedEventPublisher<ExampleEvent> publisher
= bus.createPublisher("my/topic/name", ExampleEvent.class)) {
for(int i = 0; i < 100; i++) {
ExampleEvent event = new ExampleEvent();
event.message = "The event is " + i;
publisher.deliver(event);
}
}
}
}
Because the topic for a TypedEventPublisher
is defined
at creation time the implementation may only validate it once. Also, the
TypedEventBus
implementation must check the
caller's permission to publish to the topic during the call to
createPublisher
, but should not check it again for each delivery.
Note that this means an Event Source must not share a
TypedEventPublisher
outside its own bundle.
Event Consumers can receive events by registering an appropriate Event Handler service in the Service Registry. This is a TypedEventHandler to receive events as type-safe objects, or an UntypedEventHandler to receive events as untyped Map structures.
Published events are then delivered, using the whiteboard pattern, to any Event Handler service which has registered interest in the topic to which the event was published.
Typed Events are received by registering a
TypedEventHandler
implementation. This service has a single
method notify
which receives the String topic name and
Object event data. The TypedEventHandler implementation must be
registered as a service in the service registry using the
TypedEventHandler interface.
The TypedEventHandler interface is parameterized, and so it is expected that the implementation reifies the type parameter into a specific type. In this case the Typed Event implementation must adapt the Event object into the type defined by the TypedEventHandler implementation. Implementations of this specification are free to choose their own adaptation mechanism, however it must guarantee at least the same functionality as Converter Specification.
A simple example of receiving a typed event follows:
public class ExampleEvent {
public String message;
}
@Component
public class ExampleTypedConsumer implements TypedEventHandler<ExampleEvent> {
@Override
public void notify(String topic, ExampleEvent event) {
System.out.println("Received event: " + event.message);
}
}
If the TypedEventHandler implementation is unable to reify the
type, or the required type is more specific than the reified type, then
the Typed Event Handler must be registered with the
event.type
service property. This property has a string
value containing the fully-qualified type name of the type that the
Typed Event Handler expects to receive. This type must be loaded by the
Typed Event implementation using the classloader of the bundle which
registered the Typed Event Handler service. The loaded type must then be
used as the target type when converting events. For example:
public class ExampleEvent {
public String message;
}
public class SpecialisedExampleEvent extends ExampleEvent {
public int sequenceId = Integer.MIN_VALUE;
}
@Component
@EventType(SpecialisedExampleEvent.class)
public class ExampleTypedConsumer implements TypedEventHandler<ExampleEvent> {
@Override
public void notify(String topic, ExampleEvent event) {
System.out.println("Received event: " + event.message);
// The event will always be of type SpecialisedExampleEvent
System.out.println("Event sequence id was " +
((SpecialisedExampleEvent) event).sequenceId);
}
}
By default the reified type of the TypedEventHandler will be used
as the target topic for the Event Handler. If the
event.type
property is set then this is used as the default
topic instead of the reified type. To use a specific named topic the
Typed Event Handler service may be registered with an
event.topics
service property specifying the topic(s) as a
String+ value.
public class ExampleEvent {
public String message;
}
@Component
@EventTopics({"foo", "foo/bar"})
public class ExampleTypedConsumer implements TypedEventHandler<ExampleEvent> {
@Override
public void notify(String topic, ExampleEvent event) {
System.out.println("Event received on topic: " + topic +
" with message: " + event.message);
}
}
Untyped Events are received by registering an
UntypedEventHandler
implementation. This service has a
single method notifyUntyped which receives the String
topic
name and Map
event data. The Untyped Event Handler
implementation must be registered as a service in the service registry
using the UntypedEventHandler
interface.
When delivering an event to an Untyped Event Handler the Typed Event Service must, if necessary, convert the event data to a nested map structure.
The event.topics
service property must be used when
registering an Untyped Event Hander service. If it is not, then no
events will be delivered to that Untyped Event Handler service.
public class ExampleEvent {
public String message;
}
@Component
@EventTopics({"foo", "foo/bar"})
public class ExampleUntypedConsumer implements UntypedEventHandler {
@Override
public void notifyUntyped(String topic, Map<String,Object> event) {
System.out.println("Event received on topic: " + topic
+ " with message: " + event.get("message"));
}
}
The event.topics
property may contain one or more
wildcard topics. These are Strings which contain a topic name including
one or more wildcards.
A Single-Level wildcard is used to match all topics which differ only by a single topic token within the topic String. This is done by using a “+” character to indicate the topic token which may vary.
Using a single-level wildcard means that the Event Handler must be called Events sent to topics matching the rest of the topic String. For example the component:
@Component
@EventTopics("foo/+/foobar")
public class ExampleUntypedConsumer implements UntypedEventHandler {
@Override
public void notifyUntyped(String topic, Map<String,Object> event) {
System.out.println("Event received on topic: " + topic
+ " with message: " + event.get("message"));
}
}
would receive events sent to the topics foo/bar/foobar
and foo/baz/foobar
, but not the topics foo/foobar
or
foo/bar/foobar/baz
.
The +
character in a wildcard topic must always
be the only character in the topic token that it matches, meaning
that topic names such as foo+/bar
and foo/+bar
are not valid. It is valid to use the topic name
+
to receive events on all single
level topics.
The multi-level wildcard is used to match all topics which share a given prefix. This is done by appending “/*”. to the prefix. This value means that the Event Handler must be called for Events sent to sub-topics of the named topic. For example the component:
@Component
@EventTopics("foo/*")
public class ExampleUntypedConsumer implements UntypedEventHandler {
@Override
public void notifyUntyped(String topic, Map<String,Object> event) {
System.out.println("Event received on topic: " + topic
+ " with message: " + event.get("message"));
}
}
would receive events sent to the topics foo/bar
and
foo/baz
, but not the topics foo
or
foobar/fizzbuzz
.
The *
character in a wildcard topic must always
follow a solidus /
character, and must be the final
character in the topic string, meaning that topic names such as
foo*
and foo/*/bar
are not valid. The only
exception to this rule is that it is valid to use the topic name
*
to receive events on all topics.
While it is valid to do so, using the topic *
is not
typically recommended. For a mechanism to monitor the events flowing
through the system see Monitoring Events.
Unhandled Events are events sent by an Event Source but which have no Event Handler service listening to their topic. Rather than these events being discarded, the Typed Event implementation will search the service registry for services implementing UnhandledEventHandler.
If any services are found then the Typed Event implementation will
call the notifyUnhandled
method passing the topic name and
event data to all of the registered Unhandled Event Handler
services.
public class ExampleEvent {
public String message;
}
@Component
public class ExampleUnhandledConsumer implements UnhandledEventHandler {
@Override
public void notifyUnhandled(String topic, Map<String,Object> event) {
System.out.println("Unhandled Event received on topic: " + topic);
}
}
Sometimes the use of a topic is insufficient to restrict the
events received by an event consumer. In these cases the consumer can
further restrict the events that they receive by using a filter. The
filter is supplied using the event.filter
service property,
the value of which is an LDAP filter string. This filter is applied to
the event data, and only events which match the filter are delivered to
the event handler service.
Complex events may contain nested data structures, such as DTOs,
as values in the event data. As LDAP filtering is only designed to
match against simple data this means that some event properties cannot
be filtered using the event.filter
property. The event
filter is therefore only suitable for use in matching top-level event
properties.
Note that the use of a filter is different from receiving an
event and choosing to ignore it based on its data. If an event fails
to match the filter supplied by an event handler service then it is
not delivered to that event handler. This means
that the event data remains eligible to be sent to an
UnhandledEventHandler
unless another event handler does
receive it. An event that is received, but ignored, by an event
handler service does count as having been
delivered, and so will never be sent to an
UnhandledEventHandler
.
Event Handler implementations are called by the Typed Event Bus implementation, and are expected:
-
Not to throw exceptions from their callback method
-
To return quickly - any long running tasks should be moved to another thread
If a Typed Event Bus implementation detects an Event Handler that is behaving incorrectly, either by throwing exceptions, or by taking a long time to process the event, or some other problem, then the implementation may block further event delivery to that Event Handler.
If an Event Handler is blocked by the event implementation then this situation must be logged. Also, if a blocked Event Handler service is updated then the block must be removed by the implementation. If the updated service continues to behave incorrectly then the block may be reinstated.
Event Handlers may be registered at any time, which can lead to ordering problems with respect to Event Sources publishing their first events. Specifically a late arriving Event Handler may miss the first message(s) from an early registering Event Source.
While this situation can be detected by the Event Source (for example by using an Unhandled Event Handler) or by the Event Handler (for example by using the TypedEventMonitor) doing so is relatively verbose.
In simple situations, such as watching the value of an irregularly updating Event Source, it is much easier for the Event Handler to have the last event(s) replayed to it before it starts receiving newly published events. This behaviour can be enabled using the TYPED_EVENT_HISTORY service property of the Event Handler.
The event.history
property is of type Integer
and must be greater than or equal to zero. The value of the property defines
the maximum number of historical events that should be replayed to the Event
Handler before normal event delivery begins. If the event.history
property is not set then it should be assumed to have the value zero.
When the Typed Safe Events implementation detects the registration of an Event Handler service which has requested that one or more historical events should be replayed then it should follow the following non normative steps:
-
Register the Event Handler service, but delay any event delivery until historical event delivery has completed.
-
Identify events in the retained history which match the
event.topics
defined by the Event Handler. -
Filter the identified events using the
event.filter
defined by the Event Handler. -
Sort the remaining events into chronological order.
-
Replay the last
N
events, in chronological order, whereN
is the number of events requested by the Event Handler. -
Enable the Event Handler service and begin delivering any delayed events.
The above algorithm is intended to be illustrative rather than normative and it is expected that implementations will optimise their approaches.
As retaining history is an optional feature of the Type Safe Events
implementation, and even where history is retained there may not be any history
to replay, it is possible that there will be insufficient events to supply the
number requested in event.history
. This situation is not an error,
and an Event Handler service must not require that any historical events are
delivered to it. The only guarantee is that no more than event.history
historical events will be delivered before normal event delivery commences.
The service properties that can be used to configure an Event Handler service are outlined in the following table.
Table 157.1 Service properties applicable to Event Handler services
Service Property Name | Type | Description |
---|---|---|
event.topics |
String+ |
Declares the topic pattern(s) for which the service
should be called. This service property is
required for
See TYPED_EVENT_TOPICS. |
event.type |
String |
Defines the target type into which events should be
converted before being passed to the Event Handler service. This
service property is forbidden for
See TYPED_EVENT_TYPE. |
event.filter |
String |
Defines an LDAP filter which should be tested
against the properties in the event data. Only events which pass
the filter will be passed to the the Event Handler service. This
service property is optional and permitted
for See TYPED_EVENT_FILTER. |
event.history |
Integer |
Defines the number of historical events which should
be replayed to the Event Handler Service before normal event
delivery begins. The value of this service property must be greater
than or equal to zero. This service property is
optional and permitted for both
See TYPED_EVENT_HISTORY. |
There are several possible error scenarios for Event Handlers:
-
TypedEventHandler
- If the target event type is not discoverable, that is there is no reified type information, nor is there anevent.type
property, then the target type for the event is not known. In this situation there is no way for the Typed Event implementation to correctly target an event schema, and theTypedEventHandler
must be ignored. The implementation must write a message to the log indicating which service is being ignored. -
TypedEventHandler
- If the target event type is discoverable but cannot be loaded using the class loader of the bundle which registered the Typed Event Handler service then there is no way for the Typed Event implementation to correctly target an event schema, and the Event Handler must be ignored. The implementation must write a message to the log indicating which service is being ignored. -
All Handler Types - If the event data cannot be adapted to the target type, that is the incoming data cannot be transformed due to badly mismatched property names or values, then that specific Event cannot be submitted to the Handler. The Typed Event implementation must write a message to the log indicating which service failed to receive the event. If this error occurs repeatedly then the Typed Event implementation may choose to deny list and ignore the Event Handler service. Deny listing decisions must be written to the log.
-
All Handler Types - If the
event.topics
property contains one or more invalid values then the Event Handler service must be ignored. The implementation must write a message to the log indicating which service is being ignored. -
All Handler Types - If the
event.filter
property contains an invalid value then the Event Handler service must be ignored. The implementation must write a message to the log indicating which service is being ignored. -
All Handler Types - If the
event.history
property contains an invalid value then the Event Handler service must be ignored. The implementation must write a message to the log indicating which service is being ignored.
The Typed Event implementation must register a Typed Event Bus service in the service registry. This service must implement and advertise the TypedEventBus interface.
It is not possible to know that an Event cannot be delivered until delivery is attempted. It is therefore not possible (or acceptable, given the asynchronous nature of delivery) to throw an exception to the sender of an event if there are problems delivering the event. The Event Bus service should not throw exceptions from any publication methods except:
-
NullPointerException
if the event data isnull
. -
IllegalArgumentException
if a topic name is supplied and it violates the topic name syntax.
An important part of a software system is the ability to monitor it appropriately to determine whether it is functioning correctly, without having the measurements disrupt the system. To this end the Typed Event implementation must register a TypedEventMonitor service which can be used to monitor the flow of events through the Event Bus.
Events flowing through the Typed Event Bus can be monitored using
one of the monitorEvents
methods from the
TypedEventMonitor
service. These methods return a PushStream
which delivers MonitorEvent instances each time an event is sent via the
TypedEventBus
. The monitor events contain the event topic,
the event data, and a timestamp indicating when the event was sent.
In a running system it is often useful for monitoring tools to
replay recent data immediately after a problem has occurred. For that
reason Typed Event Monitor instances may store past events so that they
can be replayed if requested. There are four monitorEvents
methods capable of replaying history:
-
monitorEvents(int) takes an
int
representing the number of past events that should be replayed from the cached history. This stream remains connected after replaying history and will continue to receive new events. -
monitorEvents(int,boolean) takes an
int
representing the number of past events that should be replayed from the cached history and a boolean indicating whether to remain connected after all available history has been replayed. Passingtrue
will ensure that only historical events are replayed. -
monitorEvents(Instant) takes an
Instant
, representing the time in the past from which the stream of monitoring events should start. -
monitorEvents(Instant,boolean) takes an
Instant
, representing the time in the past from which the stream of monitoring events should start and a boolean indicating whether to remain connected after all available history has been replayed. Passingtrue
will ensure that only historical events are replayed.
Note that storing Event History is considered a best-effort option and it is not required that the implementation supply the full set of requested events. If insufficient past events are available then the implementation must provide the maximum amount of history available.
It is not usually the case that the history for every event topic is
equally important. In fact for many topics history is unimportant, while
for others it is highly desirable to keep a small number of historical
messages indefinitely. To support this the Typed Event Service implementation
allows for history storage to be configured on a per-topic basis, with
a RangePolicy which defines both a minimum and maximum event
requirement. The minimum requirement guarantees that at least the
N
most recent events are kept for the topic and will never be
discarded in favour of events on other topics. The maximum requirement
provides a ceiling on the number of events that will be kept in history for
a given topic, ensuring that one busy topic does not dominate the whole
history. The implementation is free to discard events between the
minimum and maximum requirements at any time to manage its storage
efficiently
As the primary means of accessing historical events the Typed Event Monitor service also provides the ability to introspect and customise the historical event storage.
The most basic feature of the Event History Configuration is the
total event storage capacity. This is typically set in configuration
during startup and cannot necessarily easily be changed at runtime.
The total event storage capacity can be queried by calling getMaximumEventStorage(). This method may return 0
if no
history storage is available or -1
if no fixed limit is set.
The global history configuration is available from the getConfiguredHistoryStorage() method. This returns the entire history retention
policy for the Typed Event Service, individual configuration entries can
be obtained by calling getConfiguredHistoryStorage(String). The returned configuration provides the RangePolicy
where defining the minimum and maximum number of retained events.
Configuration entries use topic filters rather than topic names, and are therefore permitted to use wildcards. This can therefore mean that more than one configuration matches a given topic name. To ensure consistency between implementations the following disambiguation algorithm applies:
-
Identify the set of matching topic filters from the configuration
-
Extract the first token from each of the filters
-
Retain the most preferred filters based on the following preference order:
-
An exact token match
-
A single level wildcard token match
-
A multi-level wildcard match
-
-
If only one filter remains then this defines the configuration to use, otherwise remove the leading token from the retained topic filters and repeat this algorithm from the second step.
When obtaining the global configuration it is returned as a Map
with the configured topic filters used as keys. Furthermore the keys in the
map are ordered such that the most specific match for
a given topic will always be encountered first. This
can be used in conjunction with the topicFilterMatches(String) or topicFilterMatches(String,String) to easily identify which policy would apply to a
given topic.
In addition to determining the global history configuration it is
also possible to introspect the specific configuration for event history
retention. For example, to find the policy for a named topic the getEffectiveHistoryStorage(String) method will, as for the global configuration,
return an RangePolicy
defining the minimum and
maximum number of events to keep. This method must take into
account any wildcards and precedence in the global configuration to
determine the correct policy for the supplied topic name. Note that
this method can only be used for topic names, and passing a topic
filter containing wildcards will raise an IllegalArgumentException
.
In addition to viewing the currently configured history storage configuration users are able to programmatically modify the configuration at runtime.
Adding or changing the configuration for a given topic filter is possible
using the configureHistoryStorage(String,RangePolicy) method. This is used to set the required minimum
and maximum numbers of events that should be stored for each topic that matches
the supplied filter. It is invalid to pass a number less than zero for either
the minimum or maximum number of events when creating a RangePolicy
,
and it is also invalid to set a minimum greater than the maximum. In both cases an
IllegalArgumentException
is raised.
When a configuration is added or updated the implementation must ensure
that sufficient space exists to be able to hold at least the minimum number
of events for each configured topic. If the addition or update would breach
the getMaximumEventStorage() then an IllegalStateException
must be
thrown by the implementation. For this reason it is also invalid to set a
non zero minimum number of events when using a wildcard topic filter
unless there is no fixed storage limit, as
doing so makes it impossible for the implementation to know how many topics
the minimum will apply to. Passing a non-zero minimum with a wildcard topic
filter must therefore also trigger an IllegalArgumentException
if the implementation has a fixed history storage limit.
Assuming that sufficient space is available the return value of the
configureHistoryStorage
method indicates the storage space
available for this topic filter. This must be at least the minimum
requirement, and at most the maximum requirement, and is calculated
by the implementation taking into account the total available storage,
and the pre-existing configuration.
If no longer required then the configuration for a given topic filter can be deleted using removeHistoryStorage(String). When this method is called it may make zero or more historical events eligible for removal from the history, depending on the other configured filters. The implementation should ensure that any superfluous events are promptly removed from the event history and must not return them in any subsequent requests for historical data.
The Typed Event implementation bundle must provide the osgi.implementation
capability with the name TYPED_EVENT_IMPLEMENTATION. This capability can be used by provisioning
tools and during resolution to ensure that a Typed Event implementation
is present. The capability must also declare a uses constraint for the
org.osgi.service.typedevent
package and provide the version
of this specification:
Provide-Capability: osgi.implementation;
osgi.implementation="osgi.typedevent";
uses:="org.osgi.service.typedevent";
version:Version="1.1"
The RequireTypedEvent annotation can be used to require this capability.
This capability must follow the rules defined for the osgi.implementation Namespace.
The bundle providing the Typed Event Bus service must provide
capabilities in the osgi.service
namespace representing the services it is required to register. This
capability must also declare uses constraints for the relevant service
packages:
Provide-Capability: osgi.service;
objectClass:List<String>="org.osgi.service.typedevent.TypedEventBus";
uses:="org.osgi.service.typedevent",
osgi.service;
objectClass:List<String>="org.osgi.service.typedevent.monitor.TypedEventMonitor";
uses:="org.osgi.service.typedevent.monitor"
This capability must follow the rules defined for the osgi.service Namespace.
The TopicPermission class allows fine-grained control over which bundles may post events to a given topic and which bundles may receive those events.
The target parameter for the permission is the topic name.
TopicPermission
classes uses a wildcard matching algorithm
similar to the BasicPermission
class, except that solidi
('/' \u002F
) are used as separators instead of full stop
characters. For example, a name of a/b/*
implies
a/b/c
but not x/y/z
or
a/b
.
There are two available actions: PUBLISH
and
SUBSCRIBE
. These control a bundle's ability to either
publish or receive events, respectively. Neither one implies the
other.
Bundles that need to consume events must be granted permission to
register the appropriate handler service. For Example:
ServicePermission
[org.osgi.service.typedevent.TypedEventHandler
,
REGISTER
] or
ServicePermission
[org.osgi.service.typedevent.UntypedEventHandler
,
REGISTER
] or
ServicePermission
[org.osgi.service.typedevent.UnhandledEventHandler
,
REGISTER
]. In addition, bundles that consume events require
TopicPermission[ <topic>, SUBSCRIBE ]
for each topic
they want to be notified about.
Bundles that need to publish events must be granted permission to
get the TypedEventBus
service, that is
ServicePermission[ org.osgi.service.typedevent.TypedEventBus,
GET]
so that they may retrieve the Typed Event Bus and use it. In
addition, event sources require TopicPermission[ <topic>,
PUBLISH]
for each topic they want to send events to. This
includes any default topic names that are used when publishing
Bundles that need to monitor events flowing through the bus must
be granted permission to get the TypedEventMonitor
service,
that is ServicePermission[
org.osgi.service.typedevent.monitor.TypedEventMonitor, GET]
so
that they may retrieve the Typed Event Monitor and use it.
Only a bundle that provides a Typed Event implementation should be
granted ServicePermission[
org.osgi.service.typedevent.TypedEventBus, REGISTER]
and
ServicePermission[
org.osgi.service.typedevent.monitor.TypedEventMonitor, REGISTER]
to register the services defined by this specification.
The Typed Event implementation must be granted
ServicePermission[org.osgi.service.typedevent.TypedEventHandler,
GET]
,
ServicePermission[org.osgi.service.typedevent.UntypedEventHandler,
GET]
,
ServicePermission[org.osgi.service.typedevent.UnhandledEventHandler,
GET]
,
ServicePermission[org.osgi.service.typedevent.TypedEventBus,
REGISTER]
and
ServicePermission[org.osgi.service.typedevent.monitor.TypedEventMonitor,
REGISTER]
as these actions are all required to implement the
specification.
During an event notification, the Typed Event implementation's
Protection Domain will be on the stack above the handler's Protection
Domain. Therefore, if a handler needs to perform a secure operation
using its own privileges, it must invoke the doPrivileged
method to isolate its security context from that of its caller.
The event delivery mechanism must not wrap event notifications in
a doPrivileged
call.
Typed Event Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.typedevent; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.typedevent; version="[1.0,1.1)"
-
TopicPermission
- A bundle's authority to publish or subscribe to typed events on a topic. -
TypedEventBus
- The Typed Event service. -
TypedEventConstants
- Defines standard names for Typed Event properties. -
TypedEventHandler
- Listener for Typed Events. -
TypedEventPublisher
- A Typed Event publisher for a single topic. -
UnhandledEventHandler
- Listener for Unhandled Events. -
UntypedEventHandler
- Listener for Untyped Events.
A bundle's authority to publish or subscribe to typed events on a topic.
A topic is a slash-separated string that defines a topic.
For example:
org / osgi / service / foo / FooEvent / ACTION
Topics may also be given a default name based on the event type that is published to the topic. These use the fully qualified class name of the event object as the name of the topic.
For example:
com.acme.foo.event.EventData
TopicPermission
has two actions: publish
and
subscribe
.
Thread-safe
Topic name.
publish
,subscribe
(canonical order).
Defines the authority to publish and/or subscribe to a topic within the Typed Event service specification.
The name is specified as a slash-separated string. Wildcards may be used. For example:
org/osgi/service/fooFooEvent/ACTION
com/isv/*
*
A bundle that needs to publish events on a topic must have the
appropriate TopicPermission
for that topic; similarly, a bundle
that needs to subscribe to events on a topic must have the appropriate
TopicPermssion
for that topic.
The object to test for equality with this
TopicPermission
object.
Determines the equality of two TopicPermission
objects.
This method checks that specified TopicPermission
has the same
topic name and actions as this TopicPermission
object.
true
if obj
is a TopicPermission
, and has
the same topic name and actions as this TopicPermission
object; false
otherwise.
Returns the canonical string representation of the
TopicPermission
actions.
Always returns present TopicPermission
actions in the following
order: publish
,subscribe
.
Canonical string representation of the TopicPermission
actions.
Returns the hash code value for this object.
A hash code value for this object.
The target permission to interrogate.
Determines if the specified permission is implied by this object.
This method checks that the topic name of the target is implied by the
topic name of this object. The list of TopicPermission
actions
must either match or allow for the list of the target object to imply the
target TopicPermission
action.
x/y/*,"publish" -> x/y/z,"publish" is true
*,"subscribe" -> x/y,"subscribe" is true
*,"publish" -> x/y,"subscribe" is false
x/y,"publish" -> x/y/z,"publish" is false
true
if the specified TopicPermission
action is
implied by this object; false
otherwise.
The Typed Event service. Bundles wishing to publish events must obtain this service and call one of the event delivery methods.
Thread-safe
Consumers of this API must not implement this type
<T>
The type of events to be sent by the TypedEventPublisher
The type of events to be sent by the TypedEventPublisher
Creates a TypedEventPublisher for the topic automatically generated from the passed in event type.
A TypedEventPublisher that will publish events to the
topic name automatically generated from eventType
1.1
<T>
The type of events to be sent by the TypedEventPublisher
The topic to publish events to
The type of events to be sent by the TypedEventPublisher
Creates a TypedEventPublisher for the supplied topic and event type
A TypedEventPublisher that will publish events to the supplied topic
1.1
The topic to publish events to
Creates a TypedEventPublisher for the supplied topic
A TypedEventPublisher that will publish events to the supplied topic
1.1
The event to send to all listeners which subscribe to the topic of the event.
Initiate asynchronous, ordered delivery of an event. This method returns to the caller before delivery of the event is completed. Events are delivered in the order that they are received by this method.
The topic for this event will be automatically set to the fully qualified type name for the supplied event object.
Logically equivalent to calling
deliver(event.getClass().getName().replace('.', '/'), event)
NullPointerException
– if the event object is null
The topic to which this event should be sent.
The event to send to all listeners which subscribe to the topic.
Initiate asynchronous, ordered delivery of an event. This method returns to the caller before delivery of the event is completed. Events are delivered in the order that they are received by this method.
NullPointerException
– if the event object is null
IllegalArgumentException
– if the topic name is not valid
The topic to which this event should be sent.
A Map representation of the event data to send to all listeners which subscribe to the topic.
Initiate asynchronous, ordered delivery of event data. This method returns to the caller before delivery of the event is completed. Events are delivered in the order that they are received by this method.
NullPointerException
– if the event map is null
IllegalArgumentException
– if the topic name is not valid
Defines standard names for Typed Event properties.
Consumers of this API must not implement this type
The name of the service property used to indicate a filter that should be applied to events from the TYPED_EVENT_TOPICS. Only events which match the filter will be delivered to the Event Handler service.
If this service property is not present then all events from the topic(s) will be delivered to the Event Handler service.
The name of the service property used to indicate that an event handler would like to receive one or more historical events matching its TYPED_EVENT_TOPICS and TYPED_EVENT_FILTER before receiving any new data. The value of this property is an Integer greater than or equal to zero.
If this property is set then when the event hander is discovered by the whiteboard the event handler will deliver, in order, up to the requested number of historical events. This will occur before the delivery of any new events. If no history is available then zero events will be delivered. If insufficient history is available then fewer events than requested will be delivered.
The name of the implementation capability for the Typed Event specification
The version of the implementation capability for the Typed Event specification
The name of the service property used to indicate the topic(s) to which an a TypedEventHandler, UntypedEventHandler or UnhandledEventHandler service is listening.
If this service property is not present then the reified type parameter from the TypedEventHandler implementation class will be used to determine the topic.
The name of the service property used to indicate the type of the event objects received by a TypedEventHandler service.
If this service property is not present then the reified type parameter from the TypedEventHandler implementation class will be used.
The type of the event to be received
Listener for Typed Events.
TypedEventHandler
objects are registered with the Framework service
registry and are notified with an event object when an event is sent.
TypedEventHandler
objects are expected to reify the type parameter
T
with the type of object they wish to receive when implementing this
interface. This type can be overridden using the
TypedEventConstants.TYPED_EVENT_TOPICS service property.
TypedEventHandler
objects may be registered with a service property
TypedEventConstants.TYPED_EVENT_TOPICS whose value is the list of
topics in which the event handler is interested.
For example:
String[] topics = new String[] {
"com/isv/*"
};
Hashtable ht = new Hashtable();
ht.put(EventConstants.TYPE_SAFE_EVENT_TOPICS, topics);
context.registerService(TypedEventHandler.class, this, ht);
Thread-safe
The topic to which the event was sent
The event that occurred.
Called by the TypedEventBus service to notify the listener of an event.
The type of events that may be sent using this publisher
A Typed Event publisher for a single topic. Bundles wishing to publish events may obtain this object from the TypedEventBus.
All events published by this publisher are sent to the same topic, as returned by getTopic().
This object should not be shared as it will not re-validate the caller's permission to send to the target topic.
1.1
Thread-safe
Consumers of this API must not implement this type
Closes this TypedEventPublisher so that no further events can be sent. After closure all delivery methods throw IllegalStateException.
Calling close() on a closed TypedEventPublisher has no effect.
The event to send to all listeners which subscribe to the topic of the event.
Initiate asynchronous, ordered delivery of an event. This method returns to the caller before delivery of the event is completed. Events are delivered in the order that they are received by this method.
NullPointerException
– if the event object is null
IllegalStateException
– if the TypedEventPublisher has been
closed
A Map representation of the event data to send to all listeners which subscribe to the topic.
Initiate asynchronous, ordered delivery of event data. This method returns to the caller before delivery of the event is completed. Events are delivered in the order that they are received by this method.
NullPointerException
– if the event map is null
IllegalStateException
– if the TypedEventPublisher has been
closed
Get the topic for this TypedEventPublisher. This topic is set when the TypedEventPublisher is created and cannot be changed.
The topic for this TypedEventPublisher
This method allows the caller to check whether the TypedEventPublisher has been closed.
false
if the TypedEventPublisher has been
closed, true
otherwise.
Listener for Unhandled Events.
UnhandledEventHandler
objects are registered with the Framework
service registry and are notified with an event object when an event is sent,
but no other handler is found to receive the event
Thread-safe
The topic to which the event was sent
The event that occurred.
Called by the TypedEventBus service to notify the listener of an unhandled event.
Listener for Untyped Events.
UntypedEventHandler
objects are registered with the Framework service
registry and are notified with an event object when an event is sent.
UntypedEventHandler
objects must be registered with a service
property TypedEventConstants.TYPED_EVENT_TOPICS whose value is the
list of topics in which the event handler is interested.
For example:
String[] topics = new String[] {
"com/isv/*"
};
Hashtable ht = new Hashtable();
ht.put(EventConstants.TYPE_SAFE_EVENT_TOPICS, topics);
context.registerService(UntypedEventHandler.class, this, ht);
Thread-safe
The topic to which the event was sent
The event that occurred.
Called by the TypedEventBus service to notify the listener of an event.
Typed Event Annotations Package Version 1.0.
This package contains annotations that can be used to require the Typed Event implementation.
Bundles should not normally need to import this package as the annotations are only used at build-time.
-
RequireTypedEvent
- This annotation can be used to require the Typed Event implementation.
This annotation can be used to require the Typed Event implementation. It can be used directly, or as a meta-annotation.
This annotation is applied to several of the Typed Event component property type annotations meaning that it does not normally need to be applied to Declarative Services components which use the Typed Event specification.
1.0
CLASS
TYPE
, PACKAGE
Typed Event Monitoring Package Version 1.0.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest. This package has two types of users: the consumers that use the API in this package and the providers that implement the API in this package.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.typedevent.monitor; version="[1.0,2.0)"
Example import for providers implementing the API in this package:
Import-Package: org.osgi.service.typedevent.monitor; version="[1.0,1.1)"
-
MonitorEvent
- A monitoring event. -
RangePolicy
- A range policy determining how much history should be stored. -
TypedEventMonitor
- The EventMonitor service can be used to monitor the events that are sent using the EventBus, and that are received from remote EventBus instances
A monitoring event.
Consumers of this API must not implement this type
A range policy determining how much history should be stored. The minimum defines a hard limit indicating the minimum number of historical events that must be kept. The maximum defines an additional limit capping the maximum number of events that should be kept by the implementation. Events between the minimum and maximum storage limits may be discarded at any time by the implementation.
1.1
Thread-safe
Consumers of this API must not implement this type
the minimum number of events that must be kept in history
Create a range policy for a minimum history requirement. Equivalent to
RangePolicy.range(min, Integer.MAX_VALUE)
A configured RangePolicy
the maximum number of events that may be kept in history
Create a range policy for a maximum history requirement. Equivalent to
RangePolicy.range(0, max)
A configured RangePolicy
the number of events that must be kept in history
Create a range policy for an exact range. Equivalent to
RangePolicy.range(count, count)
A configured RangePolicy
Get the maximum storage requirement
This defines the maximum number of events that should be stored by the
implementation. The implementation must return at most max
events for a topic using this policy, and may return fewer subject to the
minimum constraint defined by getMinimum().
the maximum number of events that should be retained
Get the minimum storage requirement
This defines the minimum number of events that must be stored by the
implementation. If at least min
events have been sent to a
topic using this policy then there must be at least min
events returned by the history.
the minimum number of events that must be retained
Get a range policy which stores no events. Equivalent to
RangePolicy.range(0, 0)
A configured RangePolicy
the minimum number of events that must be kept in history
the maximum number of events that may be kept in history
Create a range policy for the defined range
A configured RangePolicy
Get a range policy which may store unlimited events. Equivalent to
RangePolicy.range(0, Integer.MAX_VALUE)
A configured RangePolicy
The EventMonitor service can be used to monitor the events that are sent using the EventBus, and that are received from remote EventBus instances
Thread-safe
Consumers of this API must not implement this type
the topic filter
the event retention policy to use
Configure history storage for a given topic filter.
Minimum storage settings may only be set for exact matches. It is an error to use a filter containing wildcards with a non-zero minimum history requirement.
If a minimum storage requirement is set then the Typed Events implementation must guarantee sufficient storage space to hold those events. If, after accounting for all other pre-existing miniumum storage requirements, there is insufficent storage left for this new configuration then an IllegalStateException must be thrown.
An int indicating the number of events that can be kept for this
topic given the current configuration. This will always be at
least policy.getMin()
and at most
policy.getMax()
.
NullPointerException
– if the topic filter is null
The topic filter contains invalid syntax The topic filter contains wildcard(s) and
IllegalArgumentException
– if:
getMaximumEventStorage
is not -1
and
policy.getMin()
is not
0
.
IllegalStateException
– if there is insufficient available space to
provide the additional minRequired
stored
events.
1.1
Get the configured history storage for the Typed Events implementation.
The returned Map uses topic filter strings as keys. These filter strings may contain wildcards. If multiple filter strings are able to match then the most specific match applies with the following ordering:
-
An exact topic match
-
An exact match of the parent topic and a single level wildcard as the final token
-
An exact match of the parent topic and multi-level wildcard as the final token
This ordering is applied recursively starting with the first topic token until only one candidate remains. The keys in the returned map are ordered such that the first encountered key which matches a given topic name is the configuration that will apply to that topic name.
The value associated with each key is the RangePolicy defining the number of events that will be stored.
The configured history storage
1.1
the topic filter
Get the configured history storage for a given topic filter. This method
looks for an exact match in the history configuration. If no
configuration is found for the supplied topic filter then
null
is returned.
The RangePolicy defining the number of stored events for
the topic. If no configuration is set for the topic filter then
null
will be returned.
NullPointerException
– if the topic filter is null
IllegalArgumentException
– if the topic filter contains invalid
syntax
1.1
the topic name
Get the history storage rule that applies to a given topic name. This
method takes into account the necessary precedence rules to find the
correct configuration for the named method, and so will never return
null
.
The RangePolicy defining the number of stored events for the topic. If no configuration is set for the topic filter then an RangePolicy.none() will be returned
NullPointerException
– if the topic name is null
IllegalArgumentException
– if the topic name contains invalid
syntax or wildcards
1.1
Get an estimate of the maximum number of historic events that can be stored by the TypedEvent implementation. If there is no fixed limit then -1 is returned. If no history storage is supported then zero is returned.
The maximum number of historic events that can be stored.
1.1
Get a stream of events, starting now.
A stream of event data
The requested number of historical events, note that fewer than this number of events may be returned if history is unavailable, or if insufficient events have been sent.
Get a stream of events, including up to the requested number of historical data events.
Logically equivalent to monitorEvents(history, false)
.
A stream of event data
The requested number of historical events, note that fewer than this number of events may be returned if history is unavailable, or if insufficient events have been sent.
If true
then the returned stream will be
closed as soon as the available history has been delivered
Get a stream of events, including up to the requested number of historical data events.
A stream of event data
1.1
The requested time after which historical events, should be included. Note that events may have been discarded, or history unavailable.
Get a stream of events, including historical data events prior to the supplied time.
Logically equivalent to monitorEvents(history, false)
.
A stream of event data
The requested time after which historical events, should be included. Note that events may have been discarded, or history unavailable.
If true
then the returned stream will be
closed as soon as the available history has been delivered
Get a stream of events, including historical data events prior to the supplied time.
A stream of event data
1.1
the topic filter
Delete history storage configuration for a given topic filter.
NullPointerException
– if the topic filter is null
IllegalArgumentException
– if the topic filter contains invalid
syntax
1.1
The topic filter to match against
Get a Predicate which will match the supplied topic filter against a topic name.
A predicate that will return true if the topic name being tested matches the supplied topic filter.
NullPointerException
– if the topic filter is null
IllegalArgumentException
– if the topic filter contains invalid
syntax
1.1
The topic name to match against
The topic filter to match against
Test the supplied topic filter against the supplied topic name.
A predicate that will return true if the topic name being tested matches the supplied topic filter.
NullPointerException
– if the topic filter is null
IllegalArgumentException
– if the topic filter or topic name
contain invalid syntax
1.1
Typed Event Component Property Types Package Version 1.0.
When used as annotations, component property types are processed by tools to generate Component Descriptions which are used at runtime.
Bundles wishing to use this package at runtime must list the package in the Import-Package header of the bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.service.typedevent.propertytypes; version="[1.0,2.0)"
-
EventFilter
- Component Property Type for the TypedEventConstants.TYPED_EVENT_FILTER service property of an Event Handler service. -
EventTopics
- Component Property Type for the TypedEventConstants.TYPED_EVENT_TOPICS service property of a TypedEventHandler, UntypedEventHandler or UnhandledEventHandler service. -
EventType
- Component Property Type for the TypedEventConstants.TYPED_EVENT_TYPE service property of an TypedEventHandler service.
Component Property Type for the TypedEventConstants.TYPED_EVENT_FILTER service property of an Event Handler service.
This annotation can be used on an TypedEventHandler, UntypedEventHandler or UnhandledEventHandler component to declare the value of the TypedEventConstants.TYPED_EVENT_FILTER service property.
Component Property Types
CLASS
TYPE
Service property specifying the event filter for a TypedEventHandler or UntypedEventHandler service.
The event filter.
Component Property Type for the TypedEventConstants.TYPED_EVENT_TOPICS service property of a TypedEventHandler, UntypedEventHandler or UnhandledEventHandler service.
This annotation can be used on a component to declare the values of the TypedEventConstants.TYPED_EVENT_TOPICS service property.
Component Property Types
CLASS
TYPE
Service property specifying the Event
topics of interest to an
TypedEventHandler, UntypedEventHandler or
UnhandledEventHandler service.
The event topics.
Component Property Type for the TypedEventConstants.TYPED_EVENT_TYPE service property of an TypedEventHandler service.
This annotation can be used on an TypedEventHandler component to declare the value of the TypedEventConstants.TYPED_EVENT_TYPE service property.
Component Property Types
CLASS
TYPE
Service property specifying the EventType
for a
TypedEventHandler service.
The event filter.
[1] Java Recordshttps://openjdk.org/jeps/395
The update to version 1.1 includes numerous new features and usability enhancements:
-
Event objects may now be [1] Java Records
-
Event Handler services may now use Single-Level Wildcards when registering to receive event data.
-
The TYPED_EVENT_HISTORY service property can be used to request that historical events are delivered to newly registered event handler services.
-
Unhandled event handler services may now use TYPED_EVENT_TOPICS and TYPED_EVENT_FILTER service properties to filter the events that they receive.
-
A TypedEventPublisher object can be created to optimise sending repeated events to the same topic.
-
The TypedEventMonitor service can be requested to provide only historical events, terminating the event stream once all historical data has been replayed.
-
Historical event storage can now be configured at runtime on a per-topic basis using the TypedEventMonitor.