Firing and Listening for remote CDI Events
Payara Server is able to listen to and fire CDI events across the Hazelcast cluster. The CDI events can be fired and listened to by applications on Payara Server instances as well as Payara Micro instances provided that they are connected to the same cluster.
Requirements
Hazelcast must be enabled for all Payara Server instances and they must be able to connect to the same Hazelcast cluster. See the Data Grid section for more details.
Initializing the event bus
The event bus is initialized automatically after an application is started. No additional configuration is necessary to fire and listen to remote events.
Firing remote CDI events
In order to fire a CDI event remotely, mark it with the @Outbound
annotation:
@Inject
@fish.payara.micro.cdi.Outbound
Event<String> event;
The above will create an event with a String payload, which will be observable on remote instances in the cluster. An outbound event can be fired as any other CDI event:
event.fire("This is an event");
The payload passed as an argument to the fire()
method has to implement the Serializable
interface.
An outbound event will be fired asynchronously on a remote instance. If loopback is allowed, it will be fired also on the same instance, but in a different thread. Therefore the call doesn’t block the current thread.
It’s possible to use additional qualifiers to match event with observers. Any additional qualifier used with @Outbound will mean that the event will be matched with an @Inbound listener that accepts the qualifiers.
|
Observing remote CDI events
Outbound events are observed by every CDI bean with a listener method that is marked with the @Inbound
qualifier:
public void receiveEvent(@Observes @Inbound String message) {
}
The observers may reside in any application running on one or more instances in a Hazelcast cluster, and they will listen to events fired in an application running on any instance within the same cluster. By default, events will be fired on all remote cluster instances (all instances except the one in which the event was fired).
An event will be matched with observers by the payload class, using the same rules as usual CDI events. Observers will receive events that are assignable to the observed class.
Additional options
Using CDI Qualifiers
It’s possible to tag a remote event in a type-safe way using any CDI qualifier. Only observers that match the qualifiers would receive such event.
A remote event with a qualifier @MyQualifier
can be triggered like this:
@Inject
@fish.payara.micro.cdi.Outbound
@MyQualifier
Event<String> event;
...
event.fire("This is a qualified event");
This event can be observed only by an observer that contains the qualifier:
public void receiveEvent(@Observes @Inbound @MyQualifier String message) {
}
Event name
It is possible to tag a remote event with a name. In that case, only observers that listen to events of the same name will receive such events. To fire an event with a name:
@Inject
@Outbound(eventName = "MyEvent")
Event<String> event;
To receive the above named event:
public void receiveEvent(@Observes @Inbound("MyEvent") String message) {
}
Instance name
By default, all remote instances in the same cluster will receive an outbound event, which matches the observed class and event name. If you want to target specific instances in the cluster, it is possible to define one or more target instances for an outbound event:
@Inject
@Outbound(instanceName = "Instance-1")
Event<String> event;
Several instance names can be configured with an array:
@Inject
@Outbound(instanceName = {"Instance-1", "Instance-2"})
Event<String> event;
If you are using Payara Server, the name of the DAS instance is server
by default. In the case of a separate standalone instance, use the instance’s name in the configuration. If you are using Payara Micro, the instance’s name is configured using the --name
option, or is generated by if not configured (see the section Payara Micro Instance Names).
Loopback
When an outbound event is fired, by default, it is treated as a remote message and will be delivered only to remote instances in the cluster. It will not be delivered to listeners on the same server instance.
If an event should be delivered to observers in the local instance as well, it can be done by setting the loopBack
attribute to true:
@Inject
@Outbound(loopBack = true)
Event<String> event;
Dynamic configuration
If required, events can also be fired programmatically, not only using the static @Outbound
annotation next to the injection point. Although there is no special API to support it, CDI already supports programmatic configuration of events.
The following is an example of how to configure and fire an outbound event programmatically without using any injection points:
CDI.current().getBeanManager().fireEvent("This is an event", new Outbound() {
@Override
public String eventName() {
return System.getProperty("eventname");
}
@Override
public boolean loopBack() {
return Boolean.getBoolean(System.getProperty("loopback"));
}
@Override
public String instanceName() {
return System.getProperty("instanceName");
}
@Override
public Class<? extends Annotation> annotationType() {
return this.getClass();
}
});
The above code creates a dynamic instance of the @Outbound
annotation and fires the event "This is an event"
using a bean manager retrieve via a static CDI.current
()` method.