A message bus offers facilities for publishing messages to the message handlers of registered listeners.
A message publication starts when an object is send to the bus using one of the its publication methods.
Messages can be published synchronously or asynchronously and may be of any type that is a valid sub type of the type parameter T.
Message handlers can be invoked synchronously or asynchronously depending on their configuration. Thus, there
are two notions of synchronicity / asynchronicity. One on the caller side, e.g. the invocation of the message publishing
methods. The second on the handler side, e.g. whether the handler is invoked in the same or a different thread.
Each message publication is isolated from all other running publications such that it does not interfere with them.
Hence, the bus generally expects message handlers to be stateless as it may invoke them concurrently if multiple
messages get published asynchronously. If handlers are stateful and not thread-safe they can be marked to be invoked
in a synchronized fashion using @Synchronized annotation
A listener is any object that defines at least one message handler and that has been subscribed to at least
one message bus. A message handler can be any method that accepts exactly one parameter (the message) and is marked
as a message handler using the @Handler annotation.
By default, the bus uses weak references to all listeners such that registered listeners do not need to
be explicitly unregistered to be eligible for garbage collection. Dead (garbage collected) listeners are
removed on-the-fly as messages get dispatched. This can be changed using the @Listener annotation.
Generally message handlers will be invoked in inverse sequence of subscription but any
client using this bus should not rely on this assumption. The basic contract of the bus is that it will deliver
a specific message exactly once to each of the respective message handlers.
Messages are dispatched to all listeners that accept the type or supertype of the dispatched message. Additionally
a message handler may define filters to narrow the set of messages that it accepts.
Subscribed message handlers are available to all pending message publications that have not yet started processing.
Any message listener may only be subscribed once -> subsequent subscriptions of an already subscribed message listener
will be silently ignored)
Removing a listener (unsubscribing) means removing all subscribed message handlers of that listener. This remove operation
immediately takes effect and on all running dispatch processes -> A removed listener (a listener
is considered removed after the remove(Object) call returned) will under no circumstances receive any message publications.
Any running message publication that has not yet delivered the message to the removed listener will not see the listener
after the remove operation completed.
NOTE: Generic type parameters of messages will not be taken into account, e.g. a List
will
get dispatched to all message handlers that take an instance of List as their parameter