Building a Notification Plugin

If you wish to customise the content of your notifications this can be achieved just by editing the notification templates.

Below I have tried to outline the concepts involved in creating a notification plugin. To create a notification plugin you will need to create the following classes:

Notification Components Overview

Whilst there are 3 classes to be created there are other components which work together to send the notification.

  • Notification Type - Identifies individual types of notifications and stores configuration data.
  • Notification Rule - A user configured notification, consists of a NotificationType and a Notification Recipient
  • Event - Predefined trigger which you can use to trigger your notification.
  • Event Listener - Listens for the predefined event. It filters the NotificationRules and extracts the NotificationRecipients. A Notification is then created containing these recipients and passed to the dispatcher.
  • Notification - self contained object which is used to dispatch the required notifications. It manages recipients and generates notification content.
  • Notification Recipient - An entity which will receive a notification (e.g User: bob or Group: bamboo-admin)
  • Transport - A method of notification (e.g Text Email)
  • Notification Dispatcher - Uses the Notification to dispatch individual notifications to recipients

Notification Type

The NotificationType object identifies your custom notification. Users will be able to select this from the drop down menu and provide any configuration information you require.  There are two places where you can configure notifications.  Against a plan, or globally in the Administration section in Bamboo.  When configuring notifications for a plan, you can select plan level notifications or job level notifications (since Bamboo 2.7).  To determine where your notificationType will be displayed use the scope option when defining the plugin.
You can find more information in the Notification Type Plugin Module documentation.

Notification Rule
When a user configures a notification, it will create a NotificationRule which consists of the selected NotificationType and selected NotificationRecipient. A user can select any NotificationType to go with any NotificationRecipient. When retrieving the notification rules from the database, it will retrieve rules for all notification types, you will need to filter the rules to find those which correspond to your NotificationType

Event Listener

The Event Listener will listen for an event to be fired in Bamboo which you would like to cause a notification. These events are predefined in Bamboo. You can find a list of available events as well as more information on implementing and event listener in the Bamboo Event Listener Module documentation.

A notification event listener is responsible for retrieving the Notification Rules from the database, filtering them (determining which will/wont be sent) and creating a Notification object containing the recipients that will be receiving the notification. This Notification object then needs to be passed to the NotificationDispatcher for processing. Context information is available in the event object and you can inject Managers to obtain any other required information.

Example Listener Class
The following is an example of a very basic notification listener.

public class BuildCompletedNotificationListener implements HibernateEventListener
{
    private NotificationManager notificationManager;
    private NotificationDispatcher notificationDispatcher;
    private BuildManager buildManager;

    public Class[] getHandledEventClasses()
    {
        Class[] array = {BuildCompletedEvent.class};
        return array;
    }

    public void handleEvent(Event event)
    {
        BuildCompletedEvent buildEvent = (BuildCompletedEvent) event;
        Build build = buildManager.getBuildByKey(buildEvent.getBuildPlanKey());

        Notification myNotification = new MyCustomNotification();
        myNotification.setEvent(event);

        Set<NotificationRule> rules = notificationManager.getNotificationRules(build);
        for (NotificationRule rule : rules)
        {
            NotificationType notificationType = rule.getNotificationType();
            if (notificationType instanceof MyCustomNotificationType)
            {
                if (notificationType.isNotificationRequired(event))
                {
                    NotificationRecipient recipient = rule.getNotificationRecipient();
                    myNotification.addRecipient(recipient);
                }
            }
        }

        notificationDispatcher.dispatchNotifications(myNotification);
    }

    public void setNotificationManager(NotificationManager notificationManager)
    {
        this.notificationManager = notificationManager;
    }

    public void setNotificationDispatcher(NotificationDispatcher notificationDispatcher)
    {
        this.notificationDispatcher = notificationDispatcher;
    }

    public void setBuildManager(BuildManager buildManager)
    {
        this.buildManager = buildManager;
    }
}

Notification

The Notification class is a self contained object which is used to dispatch the required notifications. You are not required to register your Notification object as a plugin module as it will be instantiated by your own Event Listener.   Notifications must implement the com.atlassian.bamboo.notification.Notification interface. There is an abstract class com.atlassian.bamboo.notification.AbstractNotification which you can extend that implements a lot of these methods for you.

A Notification will contain any context information which you will need to generate content (usually the event), a list of recipients to send the notification to and a list of recipients to exclude.

The notification class is responsible for generating the content (body) of the notifications. There is no specific generate the content of your notifications, we user Freemarker for our notifications as the templates are customisable outside of the application.

Example Content Generation
The following is an example of generating freemarker email content.  As you are instantiating this class yourself it will not be automatically injected with managers.  You will need to manually add them on creation (you can get them automatically injected into the event listener).   The templateRenderer is a bean which you will need to pass into your Notification on creation.

    @Nullable
    public String getHtmlEmailContent() throws Exception
    {
        Event event = getEvent();
        if (event != null)
        {
            Map<String, Object> context = new HashMap<String, Object>();
            populateContext(context); // put any information the context which you want available in your
                                      // freemarker template e.g. the build, buildResultsSummary etc

            try
            {
                return templateRenderer.render("notification-templates/BuildCompletedTextEmail.ftl", context);
            }
            catch (Exception e)
            {
                log.error("Could not render email content", e);
                return null;
            }
        }
        else
        {
            log.error("Event is null, could not create Email content for " + getDescription());
            return null;
        }
    }

What is a system notification type and how can I make one?

System notification types are used for sending notifications outside Bamboo's build process. For example, you might want to send a notification when Plans are disabled or deleted.

You can configure system notification types from Administration->Communication->System Notifications

To make your notification type a system notification type, simply add the line below to the body of your notificationType element in atlassian-plugin.xml

 
<scope>system</scope>

Advanced Notification Interface
If you would like more freedom over how the notification emails get generated you can implement the *com.atlassian.bamboo.notification.ExtendedNotification" interface. This will give you the generated com.atlassian.mail.Email object for you to make any other changes, e.g you could add attachments or change who the email is from based on some context information (e.g the person who made the comment being notified)

The Notification Dispatcher

Once you send your Notification object off to the dispatcher it will do the following:

  1. Retrieve the notification recipients from your Notification object
  2. The notification recipients will then evaluate a list of notification transports
  3. Retrieve and evaluate the transports which should get excluded from the notification and remove these from the transports list
  4. Each transport will then send the notification (e.g set up communication protocols and send the instant message)

Notification Recipient
A Notification Recipient is responsible for evaluating the methods of delivery and destinations of the notification. They do this by generating the appropriate Notification Transports. A Recipient can also take in configuration information from the user
A user can select any NotificationType to go with any NotificationRecipient, so you need to ensure that your plugin can handle all types of recipients. For example, the committer recipient needs to have the commits populated by your listener. Or, you need to ensure committer recipients are not added to your Notification.
Notification Recipients are also pluginable so you can create your own. You can find more information in the notification recipient plugin module documentation.

Notification Transport
Notification Transports are responsible for actually sending the notification. They set up the appropriate protocols, retrieve the content from the Notification object and fire off the resulting message through appropriate channels. The recipient is responsible for populating these with the appropriate information, e.g the email address of the IM address). There are three types of transports in bamboo currently: Multipart Email, Text Email and Instance Message.

Questions?

Why do I have excluded recipients?
Recipients are not evaluated till dispatch, which means if a user has configured a group recipient, you can not control who out of that group will or wont recieve a notification. So we have provided a mechanism to allow you to exclude recipients from the list (which will also get dispatched at run time).

For example, the build-commented notification we do not want to get sent to the user who actually created the comment. We would add that user to the list, and when the groups get evaluated this user would get excluded but all other members would still receive the notification.

Can I just provide html content and not text content?
It is not mandatory to send out both html and text content, however, as a user can select to JUST recieve text emails they will not get sent anything if the email is blank, so we recommend always providing a text option.

What is a multipart email?
A Multipart email contains both text content and HTML content. It is then up to the users mail browser to select which type of email they would like to view.

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport