Notifications Module
![]() | Handle notifications |
Type | JAR |
Category | API |
Developed by | Unknown |
Rating | |
License | GNU Lesser General Public License 2.1 |
Table of contents
Description
Module that get the notifications to display to a user and handle the notification statuses.
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 != null && 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.
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.eventstream.Event
#set ($app = "$event.application")
#set ($icon = 'bell')
#if ($app == 'xwiki')
#set ($app = 'XWiki')
#set ($icon = 'file')
#end
#set ($document = $xwiki.getDocument($event.document))
<div class="clearfix">
<div class="col-xs-2 notification-icon">
$services.icon.renderHTML($icon)
</div>
<div class="col-xs-10">
<p><strong>$app</strong></p>
<p><strong>[$!escapetool.xml($event.type)]</strong> <a href="$!escapetool.xml($document.getURL())">$!escapetool.xml($document.getRenderedTitle('html/5.0'))</a></p>
#if ("$!event.user" != '')
#set ($userDoc = $xwiki.getDocument($event.user))
<p>by <a href="$userDoc.getURL()">$userDoc.display('first_name', 'view') $userDoc.display('last_name', 'view')</a></p>
#end
<p><small>$escapetool.xml($xwiki.formatDate($event.date))</small></p>
</div>
</div>
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(Event eventNotification) throws NotificationException
{
// custom code here
}
@Override
public List<String> getSupportedEvents()
{
return EVENTS;
}
}
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;
}
}