9. EventBus API in Tigase

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 The Administration Guide.

9.1. EventBus API

To create instance of EventBus use the following code:

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.

9.1.1. Events

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

Serialized event class.

public class SampleSerializedEvent implements Serializable {
    private JID data;
    public JID getData() {
        return this.data;
    }
    public void setData(JID data) {
        this.data = data;
    }
}

Event class.

public class SampleEvent {
    private JID data;
    public JID getData() {
        return this.data;
    }
    public void setData(JID data) {
        this.data = data;
    }
}

XML Element event(deprecated)

<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.

9.1.2. 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.

9.1.3. 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.

<net.tigase.sample.SampleSerializedEvent>
    <data>[email protected]</data>
</net.tigase.sample.SampleSerializedEvent>

9.1.4. Firing events

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

Firing serialized event.

EventBus eventBus = EventBusFactory.getInstance();
SampleSerializedEvent event = new SampleSerializedEvent();
eventBus.fire(event)

Firing simple event.

EventBus eventBus = EventBusFactory.getInstance();
SampleEvent event = new SampleEvent();
eventBus.fire(event)

Firing event based on XML Element(deprecated)

EventBus eventBus = EventBusFactory.getInstance();
Element event = new Element("tigase.eventbus.impl.Event1");
eventBus.fire(event)

9.1.5. 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.

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.

public class SomeConsumer {

    @HandleEvent
    public void event1(Event12 e) {
    }

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

Handling XML events

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).

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:

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:

<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:

eventBus.addListener("net.tigase.sample", null,  event -> {});
eventBus.addListener(null, null,  event -> {});
  • This listener will be called for each event with given package name (XML based, or serialized class based).

  • 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.

class MainEvent { }
class SpecificEvent extends MainEvent {}

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

eventBus.fire(new SpecificEvent());
  • Will be called, because this is listener stricte for SpecificEvent.

  • Will be called, because SpecificEvent extends MainEvent.