[[eventBusAPI]]
= EventBus API in Tigase
:author: Bartosz Małkowski <bartosz.malkowski@tigase.net>
:version: v1.1 June 2021. Reformatted for v8.0.0.

:toc:
:numbered:
:website: http://tigase.net/

EventBus is a custom publish-subscribe mechanism which allows for the use of Event Listener within Tigase Server.
For a more detailed overview of EventBus and it's features, please visit link:http://docs.tigase.org/tigase-server/snapshot/Administration_Guide/html/#eventBus[The Administration Guide].

== EventBus API

To create instance of EventBus use the following code:

[source,java]
-------
EventBus eventBus = EventBusFactory.getInstance();
-------

NOTE: Remember, that EventBus is asynchronous.
All handlers are called in a different thread than the thread that initially fired the event.

=== Events

Events may be defined in two ways: as a class +++<del>+++or as an XML element+++<del>+++ (XML/Element based events are deprecated since version 8.2 and will be removed in version 9.0).

.Serialized event class
[source,java]
----
public class SampleSerializedEvent implements Serializable {
    private JID data;
    public JID getData() {
        return this.data;
    }
    public void setData(JID data) {
        this.data = data;
    }
}
----

.Event class
[source,java]
----
public class SampleEvent {
    private JID data;
    public JID getData() {
        return this.data;
    }
    public void setData(JID data) {
        this.data = data;
    }
}
----

.+++<del>+++XML Element event+++<del>+++ (deprecated)
[source,xml]
-------
<EventName xmlns="tigase:demo">
  <sample_value>1</sample_value>
</EventName>
-------


NOTE: Events defined as XML element and class implementing `Serializable` interface will be distributed to all servers in cluster.
Event `SampleEvent` will be broadcast only in the same instance what fired the event.

==== Requirements for class-based events

* Default, explicit, public, paremeter-less constructor is mandatory.
* If the event should be delivered to all cluster nodes then it *MUST* implement `Serializable` interface.
* Variables serialisation follows `Serializable` semantics, which means that `final`, `static` nor `transient` fields will be skipped. What's more, fields with `null` value will not be serialised neither.

==== Serialisation of class-based events

Class based events are serialized (if it is required and possible) to XML element.
Name of XML element is taken from full name of class:

.Class based event serialized to XML
[source,xml]
----
<net.tigase.sample.SampleSerializedEvent>
    <data>sample@data.tigase.net</data>
</net.tigase.sample.SampleSerializedEvent>
----

=== Firing events

To fire event, just get instance of EventBus and call method `fire()`.

.Firing serialized event
[source,java]
----
EventBus eventBus = EventBusFactory.getInstance();
SampleSerializedEvent event = new SampleSerializedEvent();
eventBus.fire(event)
----

.Firing simple event
[source,java]
----
EventBus eventBus = EventBusFactory.getInstance();
SampleEvent event = new SampleEvent();
eventBus.fire(event)
----

.+++<del>+++Firing event based on XML Element+++<del>+++ (deprecated)
[source,java]
----
EventBus eventBus = EventBusFactory.getInstance();
Element event = new Element("tigase.eventbus.impl.Event1");
eventBus.fire(event)
----



=== Handling events

To handle fired event, we have to register listener in EventBus.
When listener is registered, EventBus automatically subscribes for this type of event in all instances in cluster.

Depends on expected event type, we have to decide what type of listener we should register.

==== Handling class based events

This option is reserved for class based events only.
It doesn't matter if it is serialized class or not.

[source,java]
----
eventBus.addListener(SampleEvent.class, new EventListener<SampleEvent>() {

    @Override
    public void onEvent(SampleEvent event) {
    }
});

----

To make registering listeners more easy, you can use method `registerAll()` from EventBus.
This method registers all methods given class, annotated by `@HandleEvent` as listeners for event declared as the method argument.

[source,java]
----
public class SomeConsumer {

    @HandleEvent
    public void event1(Event12 e) {
    }

    public void initialize() {
        eventBus.registerAll(this);
    }
}
----

==== +++<del>+++Handling XML events+++<del>+++

.Click to see details (XML/Element based events are deprecated since version 8.2 and will be removed in version 9.0)
[%collapsible]
====

To handle XML events we have to register listener for specific event package and name.
In our example, package is empty because event name has no package declared (see also <<Filtering events>>).

[source,java]
----
eventBus.addListener("", "EventName", new EventListener<Element>() {
    @Override
    public void onEvent(Element event) {

    }
});
eventBus.addListener("tigase.eventbus.impl", "Event1", new EventListener<Element>() {
    @Override
    public void onEvent(Element event) {

    }
});
----

Because serialized class events, ale transformed to XML elements, we are able to listen for XML representation of class based event.
To do that, we have to register listener for specific package and class name:

[source,java]
----
eventBus.addListener("net.tigase.sample", "SampleSerializedEvent", new EventListener<Element>() {
    @Override
    public void onEvent(Element event) {

    }
});
----
====

[IMPORTANT]
====
XML events created on others cluster node, will have attribute `remote` set to `true` and attribute `source` set to event creator node name:

[source,xml]
-------
<EventName xmlns="tigase:demo" remote="true" source="node1.example">
  <sample_value>1</sample_value>
</EventName>
-------
====

==== Filtering events

Sometimes you may want to receive many kinds of events with the same handler.
EventBus has very simple mechanism to generalization:

[source,java]
----
eventBus.addListener("net.tigase.sample", null,  event -> {}); <1>
eventBus.addListener(null, null,  event -> {}); <2>
----
<1> This listener will be called for each event with given package name (XML based, or serialized class based).
<2> This listener will be called for ALL events (XML based, or serialized class based).

In case of class based events, EventBus is checking class inheritance.

[source,java]
----
class MainEvent { }
class SpecificEvent extends MainEvent {}

eventBus.addListener(SpecificEvent.class, event -> {}); <1>
eventBus.addListener(MainEvent.class, event -> {}); <2>

eventBus.fire(new SpecificEvent());
----

<1> Will be called, because this is listener stricte for `SpecificEvent`.
<2> Will be called, because `SpecificEvent` extends  `MainEvent`.