Notifications Module

Version 7.2 by Guillaume Delhumeau on 2017/03/16 17:38

bellHandle notifications
TypeJAR
CategoryAPI
Developed byUnknown
Rating
0 Votes
LicenseGNU Lesser General Public License 2.1

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: 

package org.xwiki.platform.blog.events;

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:

package org.xwiki.platform.blog.events;

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.

## Default renderer for any kind of notification.
## 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.

Example:

/**
 * 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

observationManager.notify(new BlogPostPublishedEvent(), "org.xwiki.platform:xwiki-platform-blog-api", document);

Example of code that send a notification when a blog post is saved

package org.xwiki.platform.blog.internal;

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;
   }
}
Tags:
    

Get Connected