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 thatfinal
,static
nortransient
fields will be skipped. What’s more, fields withnull
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 totrue
and attributesource
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
extendsMainEvent
.