Event Stream API

Last modified by Admin on 2024/12/11 00:32

cogAPI for Event Stream events
TypeJAR
CategoryAPI
Developed by

XWiki Development Team

Rating
1 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Installable with the Extension Manager

Description

The Event stream module offers APIs to manipulate activity events. An activity event is a recorded event that occurred at some point in the wiki.

This API replaces the older, deprecated, Activity Stream Plugin.

You can define custom events inside wiki pages through the EventClass XObject.

Events

Events are identified by:

  • an identifier unique for each event
  • a group identifier used for all the events caused during the same action
  • the exact date and time when the event occurred
  • an importance which allows to order events in the same group, or in the same stream

Events contain:

  • a title
  • a body
  • and a map of custom properties

Events are categorized into:

  • the application that created them, like blog, user statuses, or the general wiki
  • an eventual sub-stream inside the application, for example a space for wiki events, or a certain group for user statuses
  • the particular type of event, like adding a comment, updating an attachment, setting a new user status

Events target:

  • the wiki,
  • the space,
  • and the document affected by the event
  • and an eventual entity inside the document, for example an individual attachment for attachment events, or an individual object for comment events.

Events can store some more information about the context in which they occur:

  • the user that caused the event
  • the version of the target document at the time that the event occurred
  • the display title of the target document at the time that the event occurred
  • the requested URL that caused the event

If the Solr-based event store is enabled (the default), events can also store a map of custom properties.

The default implementation support the following types for the properties values:

  • String
  • Double
  • Float
  • Long
  • Integer
  • Boolean
  • Date
  • byte[]
  • Iterable or array of the previously listed types in input (converted to List)

Stores

A Solr-based store is the default location where events are stored and from which they are retrieved. 

The legacy store (database one) is currently still populated with the events and used as fallback for deprecated APIs which are not yet fully supported by the new event store API and/or Solr implementation (a good example being the HQL based search API which will most probably never be supported by the new store).

Code Samples

Java

Adding an event to the event store

  // [...]

 // Some imports we will need :

import org.xwiki.eventstream.Event;
import org.xwiki.eventstream.EventFactory;
import org.xwiki.eventstream.EventStore;

 // [...]

 // Some requirements to add events :

 @Inject
 private EventFactory eventFactory;

 @Inject
 private EventStore eventStore;

 // [...]

 // Adding an event to the stream :
 Event event = this.eventFactory.createEvent();
  event.setDocument(someDocument.getDocumentReference());

  event.setApplication("yowler"); // (It's like twitter, but only for cats)
 event.setType("yowl");

  Map<String, String> params = new HashMap<String, String>();
  params.put("yowled", "meoooow !");

  event.setParameters(params);

 // All write operation of the store are asynchonous and return a CompletableFuture
 CompletableFuture<Event> future = this.eventStore.saveEvent(event);

 // Wait for the event to be stored
 future.get();

Note that directly adding an event to the store is generally a bad practice and the best practice is to sent an event implementing org.xwiki.eventstream.RecordableEvent in the ObservationManager.

Retrieving events from the store

  import org.xwiki.eventstream.EventSearchResult;
 import org.xwiki.eventstream.query.SimpleEventQuery;
 import org.xwiki.eventstream.query.SortableEventQuery.SortClause.Order;

  SimpleEventQuery query = new SimpleEventQuery();
 // Only return events for which the application is "yowler"
 query.eq(Event.FIELD_APPLICATION, "yowler");
 // Since 13.9 it's possible to manipulate custom event parameters
 query.parameter().eq("mycustomperameter", "myvalue");
 // Since 14.2 the custom parameters are deprecated and replaced with more generic custom properties with support for various other types than String
 query.custom().eq("mycustomnumber", 42);
 // Search for events in which the custom list property "mycustomlist" has one of its elements equal to "element1"
 query.custom(List.class).eq("mycustomlist", "element1");
 // Since 14.4RC1 it's possible to search for text contained in a field
 query.contains(Event.FIELD_DOCUMENTTITLE, "Hello");
 // Filter out all events triggered by superadmin
 query.not().eq(Event.FIELD_USER, "xwiki:XWiki.superadmin");
 // Sort events by date in descending order
 query.addSort(Event.FIELD_DATE, Order.DESC);
 // Limit the number of result to return
 query.setLimit(15);

  EventSearchResult result = this.eventStore.search(query)

  result.stream().forEach((event) -> {
   // Do anything with those events
 });

Define custom events in wiki pages

The EventClass XObject allows anyone with the admin rights on the current wiki to define a custom event. In order to demonstrate how a custom event definition can be useful, we will use one event defined in the Blog application that should be triggered when a blog post is published, and "translate" it into its equivalent XObject definition.

First of all, we have to create an XObject of type EventClass in any wiki page (a hidden page with restricted access rights is still preferred). This XObject has several parameters : 

  • Application: The name of the application related to the event;
  • Event Type: The type (name) of the event;
  • Event Icon: The name of the icon associated to the event;
  • Event description: A short description of the event that can be displayed to the user;
  • Listen to …: A list of events that can be used to trigger this custom event. Only one event in this list is needed to trigger the custom event.
  • Object Type: A list of XObject types that should be linked to the document that is the source of the event, note that you can leave this field blank in case where one of the triggering events defined in the Listen to … field doesn’t have a particular document attached to it;
  • Validation Template: In this template, you can define specific conditions in order to allow (or not) the triggering of the custom event :
    • The template comes with two additional context variables :
      • event: the event, which is an instance of one of the classes defined in the Listen to … field;
      • source: the source of the event;
    • In order to validate the triggering of the custom event, the template should affect the value "true" to the variable "xreturn". Example: #set ($xreturn = true);

    • If the Validation Template field is left blank, the template rendering will be ignored.
  • Target: In this template, you can define a list of users to which the event will be sent. Other users will not see this event.
    • The template comes with two additional context variables :
      • event: the event, which is an instance of one of the classes defined in the Listen to … field;
      • source: the source of the event;
    • In order to generate the target list, the template should affect a list of user id (serialized references of the users) to the variable "xreturn". Examples: #set ($xreturn = ['xwiki:XWiki.UserA', 'xwiki:XWiki.UserB']) or #set ($xreturn = [$services.model.serialize($event.user, 'default')]).

The Application and the Event description parameters can both be set with translation keys in order to be displayed in multiple languages.

Here is one example of an XObject that copy the same comportment of the BlogPostPublishedEvent in the Blog application :

XObjectEventExample.png

Once your XObject is defined … everything is done! The event is now registered. If you use the notifications application provided by default with XWiki Platform, every user should now see the custom event in their notification center, and should be able to subscribe to it : 

XObjectEventNotificationCenter.png

User notifications preferences are not deleted when you remove a custom event from your wiki. If you create a new custom event with the same Event Type, the user preferences will be restored.

Example of an event (notification) sent to a particular user only if the wiki handle the TargetableEvents

  • field: Validation Expression:
      #set ($xreturn = true)
  • field: Target:
      ## Example: send the event to the creator of the document only
     #set ($document = $xwiki.getDocument($event.document))
     #set ($xreturn = [$services.model.serialize($document.creatorReference, 'default')])

When to use Untyped Event instead of creating your own RecordableEvent

If you are a Java developer, you may prefer to create your own class that implement the RecordableEvent interface (as explained in Tutorial: How to send notifications).

But if you don't want to add a Java module in your extension you should used this Custom Event mechanism. Old XWiki versions will only ignore this XObject.

Events sent by the Event Stream

The Event Stream can send two new events :

In order to avoid event loops (an event from the observation manager that adds a new event to the event stream that triggers another event from the observation manager that adds new events to the event stream and so on …), the default implementation of the Event Stream will not allow more than one EventStreamEvent to be added to the Event Stream in the same execution context.

You can find out more checking out this module source code :

https://github.com/xwiki/xwiki-platform/tree/master/xwiki-platform-core/xwiki-platform-eventstream

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager).

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Dependencies

Dependencies for this extension (org.xwiki.platform:xwiki-platform-eventstream-api 16.10.1):

Get Connected