Remote CDI Events in Payara Platform

Photo of Luqman Saeed by Luqman Saeed

The Jakarta Contexts and Dependency Injection API is the standard dependency injection framework on the Jakarta EE Platform. The latest version of the CDI specification that shipped withJakarta EE 10 is CDI 4.0. This release features a split of the core CDI API into Lite and Full. CDI Lite is designed to run in more restricted environments, and features a subset of the original features. CDI Full contains the Lite and all other features that were in core CDI in previous Jakarta EE releases.

One of the features of Jakarta CDI is the events mechanism. CDI events allow for loosely coupled, typesafe communication between different application components with no compile-time dependency between them. The publisher-subscriber paradigm of the observer design pattern is at the core of CDI events, which comprises two parts: the event object and event observers.

The event object or event payload is the data that is transmitted to observers of the given event when it is fired. The payload can be any valid Java type. An event observer is a component that registers for an event, optionally qualifying the event through qualifiers. Firing a CDI event is as simple as wrapping the event payload in the jakarta.enterprise.event.Event and calling the Event#fire method. The code snippet below shows the injection of the Event object and firing a jakarta.json.JsonObject event payload when a HelloEntity is persisted.

public class PersistenceService {

@Inject
Event<JsonObject> helloEvent;

@PersistenceContext
private EntityManager entityManager;

public HelloEntity save(final HelloEntity helloEntity) {
entityManager.persist(helloEntity);

JsonObject eventPayload = Json.createObjectBuilder()
.add("title", "HelloEntity Persisted")
.add("entityId", helloEntity.getId())
.add("date", helloEntity.getDateCreated().toString())
.build();

helloEvent.fire(eventPayload);

return helloEntity;
}
}

The code above injects the Event object, wrapping a JsonObject as payload. Then when a HelloEntity is persisted, the fire method is called with a fully constructed JsonObject. All event listeners will receive this passed event payload. For example the listener shown in the code snippet below will receive the passed JsonObject instance. 

protected void listen(@Observes final JsonObject helloEvent) {
log.log(Level.INFO, helloEvent::toString);
}

Registering for a CDI event is as simple as annotating a method parameter with jakarta.enterprise.event.Observes annotation. The annotated type must be the same as the payload type of the event to be observed. In the above code snippet, the annotated type is a JsonObject type. At runtime, the CDI implementation will pass the constructed instance of the JsonObject to this method. And the method can then do anything it likes with the passed payload.

Remote CDI Events

The event mechanism looked at so far is for a single application. The Payara Platform has a built-infeature for firing remote CDI events. This feature allows a CDI event to be fired and observed by all applications within a givenHazelcast cluster. Applications deployed to Payara Server or Payara Micro instances within a given cluster can fire and observe CDI events. To use this feature, you need to add the payara-api dependency to your project as shown below.

<dependency>
<groupId>fish.payara.api</groupId>
<artifactId>payara-api</artifactId>
<version>6.2022.1</version>
<scope>provided</scope>
</dependency>

With the dependency in place, we can fire remote CDI events by just annotating the Event object with the fish.payara.micro.cdi.Outbound CDI qualifier. The code snippet below shows the JsonObject event now annotated with @Outbound to transform it into a remote CDI event. 

@Inject
@Outbound
Event<JsonObject> helloEvent;

The JsonObject event, when fired, can now be observed by all Payara deployed applications that are on the same Hazelcast cluster, observing with fish.payara.micro.cdi.Inbound qualifier. The JsonObject observer shown above is reproduced below, with the @Inbound qualifier to observe for remote Payara CDI events.

protected void listen(@Observes @Inbound final JsonObject helloEvent) {
log.log(Level.INFO, helloEvent::toString);
}

This observer could be in a different application on any Payara Server or Payara Micro instance within the cluster, the event will be routed to it. This is one of the features of the Payara Platform built on top of the base Jakarta CDI. For more custom features, please take a look at the Payara documentation page. Also check out ourresources sectionfor various guides on different aspects of Jakarta EE application development with the Payara Platform and Payara Cloud.  

For CDI in particular, make sure you have read ourJakarta EE CDI Fact Sheet:
Jakarta CDI-1

 

Comments