Notifications API
Handle notifications |
Type | JAR |
Category | API |
Developed by | |
Rating | |
License | GNU Lesser General Public License 2.1 |
Bundled With | XWiki Standard |
Table of contents
Description
Module that get the notifications to display to a user and handle the notification statuses.
Script Service
This module introduces a script service available like this:
See the code with the available methods.
Tutorial: How to send notifications
Principle
In XWiki, a notification is simply an event sent by some application, stored by the Event Stream Module and then displayed in the notifications menu.
Recordable Event
In order to indicate that the event you send through the Observation Manager must be stored by the Event Stream, the event must implement the RecordableEvent interface.
Example:
import org.xwiki.eventstream.RecordableEvent;
/**
* Event sent when a blog post has been published.
*
* @version $Id: c89002f510111a9e9162394fa35fc811d50eb482 $
* @since 9.2RC1
*/
public class BlogPostPublishedEvent implements RecordableEvent
{
@Override
public boolean matches(Object otherEvent)
{
return otherEvent instanceof BlogPostPublishedEvent;
}
}
Targetable Event
If you want that only some users or some groups receive the notification (by default it is everybody), your event need to implement the TargetableEvent interface. Then, you can specify a list of targets which are the ids of the users or the groups.
Note that if you don't specify a list of targets, your event will be considered as a standard RecordableEvent so it will be sent to all users watching for this event.
XWiki <12.3 only users could be targeted with Targetable events, the support of group has been added in XWiki 12.3RC1.
XWiki 12.8+ those events are not concerned anymore by the inclusive notification filters. It means that for those events, even if the user is not actively watching the location from were the event is sent, he will receive the notifications. However, if the user created an exclusive filter, this filter will be honoured and the notification won't be received.
Recordable Event Converter
You can customize the way an event is stored by the Event Stream by implementing your own RecordableEventConverter.
The role of this component is to convert an event from the Observation Module to an event from the Event Stream Module, that the event stream can store. If you want to store custom parameters, you need to create your own converter.
By default, the DefaultRecordableEventConverter is used.
Recordable Event Descriptor
In order to be see the notification, a user must enable the notification for the event type you have created. To be listed in the user notification settings, you must provide a RecordableEventDescriptor, which is a component that give some description about your event type to the users.
Example:
import javax.inject.Named;
import javax.inject.Singleton;
import org.xwiki.component.annotation.Component;
import org.xwiki.eventstream.RecordableEventDescriptor;
/**
* Descriptor for the event {@link BlogPostPublishedEvent}.
*
* @version $Id: 6f28643529fd7f1bb4477afa7c9117f75cc2b84c $
* @since 9.2RC1
*/
@Component
@Singleton
@Named("BlogPostPublishedEvent")
public class BlogPostPublishedEventDescriptor implements RecordableEventDescriptor
{
@Override
public String getEventType()
{
return BlogPostPublishedEvent.class.getCanonicalName();
}
@Override
public String getApplicationName()
{
return "blog.applicationName";
}
@Override
public String getDescription()
{
return "blog.events.blogpostpublished.description";
}
@Override
public String getApplicationIcon()
{
return "rss";
}
}
Notification Displayer
By default, all notifications are displayed using the notification/default.vm template.
## Each application should create its own.
## The variable "$event" contains the event to display.
## See: org.xwiki.notifications.CompositeEvent
#template('notification/macros.vm')
#set ($app = "$!event.events.get(0).application")
#set ($icon = 'bell')
#if ($app == 'xwiki')
#set ($app = $services.localization.render('core.events.appName'))
#set ($icon = 'file')
#end
#displayNotificationEvent($icon, $app, $event)
You can override this template for your event type by creating a template called notification/{canonical name of your event class}.vm.
Example: notification/org.xwiki.platform.blog.events.BlogPostPublishedEventDescriptor.vm.
An other way to provide a custom displayer is to create a component that implement the NotificationDisplayer role.
* Implement a {@link NotificationDisplayer} for the event type
* {@link org.xwiki.platform.blog.events.BlogPostPublishedEvent}.
*
* @version $Id: ebf9735007f36e701c2ed07420bc972b56da7982 $
* @since 9.2RC1
*/
@Component
@Singleton
@Named(BlogNotificationDisplayer.EVENT_TYPE)
public class BlogNotificationDisplayer implements NotificationDisplayer
{
/**
* Name of the event type that this displayer handle.
*/
public static final String EVENT_TYPE = "org.xwiki.platform.blog.events.BlogPostPublishedEvent";
private static final List<String> EVENTS = Arrays.asList(EVENT_TYPE);
@Override
public Block renderNotification(CompositeEvent eventNotification) throws NotificationException
{
// custom code here
}
@Override
public List<String> getSupportedEvents()
{
return EVENTS;
}
}
Note that the renderNotification method takes a CompositeEvent: this is because the events are not rendered alone but by group of similar events. This allows for example to display only one notification for all likes on a page.
Example of code to send a notification
Example of code that send a notification when a blog post is saved
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.xwiki.bridge.event.DocumentCreatedEvent;
import org.xwiki.bridge.event.DocumentUpdatedEvent;
import org.xwiki.component.annotation.Component;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.SpaceReference;
import org.xwiki.observation.AbstractEventListener;
import org.xwiki.observation.ObservationManager;
import org.xwiki.observation.event.Event;
import org.xwiki.platform.blog.events.BlogPostPublishedEvent;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
/**
* Send the {@link BlogPostPublishedEvent} when a blog post is published.
*
* @version $Id: 6a3f33b7e415f7d967865024087d755448db2dc9 $
* @since 9.2RC1
*/
@Component
@Singleton
@Named(BlogDocumentSavedListener.NAME)
public class BlogDocumentSavedListener extends AbstractEventListener
{
/**
* Name of the listener.
*/
public static final String NAME = "Blog Document Saved Listener";
@Inject
private ObservationManager observationManager;
/**
* Construct a BlogDocumentSavedListener.
*/
public BlogDocumentSavedListener()
{
super(NAME, new DocumentCreatedEvent(), new DocumentUpdatedEvent());
}
@Override
public void onEvent(Event event, Object source, Object data)
{
XWikiDocument document = (XWikiDocument) source;
// Send a BlogPostPublishedEvent if the blog post is published but was not before
final DocumentReference blogPostClass = new DocumentReference("BlogPostClass", new SpaceReference("Blog",
document.getDocumentReference().getWikiReference()));
BaseObject blogPost = document.getXObject(blogPostClass);
BaseObject previousBlogPost = document.getOriginalDocument().getXObject(blogPostClass);
if (isPublished(blogPost) && !isPublished(previousBlogPost)) {
observationManager.notify(new BlogPostPublishedEvent(), "org.xwiki.platform:xwiki-platform-blog-api",
document);
}
}
private boolean isPublished(BaseObject blogPost)
{
return blogPost != null && blogPost.getIntValue("published") == 1 && blogPost.getIntValue("hidden") == 0;
}
}
Notification Email Renderer
By default, all notifications are displayed using the notification/email/default.html.vm and notification/email/default.plain.vm templates.
You can override these templates for your event type by creating templates called notification/email/{canonical name of your event class}.html.vm and notification/email/{canonical name of your event class}.plain.vm, respectively for emails clients that handle HTML and emails clients that do not.
An other way to provide a custom email renderer is to create a component that implement the NotificationEmailRenderer role.
@Singleton
@Named("canonical name of your event class")
public class CustomNotificationEmailRenderer implements NotificationEmailRenderer
{
@Override
public String renderHTML(CompositeEvent compositeEvent) throws NotificationException
{
return "a string containing HTML code for email clients that handle HTML";
}
@Override
public String renderPlainText(CompositeEvent compositeEvent) throws NotificationException
{
return "a plain text string for email clients that do not handle HTML";
}
@Override
public String generateEmailSubject(CompositeEvent compositeEvent) throws NotificationException
{
// not used yet
return "a plain text string for the email's subject, when a notification is sent on real-time";
}
}
Tutorial: How to create your own notification filter
On the Java-side, you can implement your own component for the role org.xwiki.notifications.NotificationFilter.
On the wiki-side, you must also create an UI Extension with the Extension Point ID "notification.profile.filter" and the name should be the name of the event you want to filter.
Create custom notification templates
NotificationDisplayerClass XObject.
, an administrator can create custom notifications templates directly through wiki pages. This is done by using theIn order to demonstrate how this system works, we will use this very XObject to define a custom template for "update" notifications.
The NotificationDisplayerClass XObject takes two properties :
- Event Type : The type of event that should be overridden
- Notification Template : The notification template that should be used instead of the default one
With the object described above, here is the result in the notification center (the two images represent how the notifications are displayed before and after defining the XObject).
For emails
, you can do the same for email notifications.
You need to use the class NotificationEmailRendererClass which takes four properties :
- Event Type : The type of event that should be overridden
- HTML Template : The template used for the HTML version of the email
- Plain text Template : The template used for the plain text version of the email
- Email Subject Template : The template used to generate the email subject (not used yet)
Create your own Notification Filter
Developers can create their own Notification Filter. For that, they need to create their own implementation of NotificationFilter
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-notifications-api 16.9.0):