{"id":37777,"date":"2015-06-09T05:55:56","date_gmt":"2015-06-09T12:55:56","guid":{"rendered":"http:\/\/localhost\/exoblog\/?p=8920"},"modified":"2015-06-09T05:55:56","modified_gmt":"2015-06-09T12:55:56","slug":"tutorial-how-to-extend-the-exo-platform-notification-system","status":"publish","type":"post","link":"https:\/\/www.exoplatform.com\/blog\/tutorial-how-to-extend-the-exo-platform-notification-system\/","title":{"rendered":"Tutorial: How to extend the eXo Platform notification system"},"content":{"rendered":"<p><a href=\"https:\/\/www.exoplatform.com\/blog\/2015\/06\/09\/tutorial-how-to-extend-the-exo-platform-notification-system\/\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/Extending-Platform-Notifications.jpg\" alt=\"Extending-Platform-Notifications\" width=\"650\" height=\"220\" class=\"aligncenter size-full wp-image-8937\"><\/a><\/p>\n<p>In <a href=\"https:\/\/lanbk52.wordpress.com\/2015\/04\/18\/building-an-auto-image-slideshow-using-ajaxdom-object-with-exo-driverconnector-api\/\" class=\"broken_link\" target=\"_blank\" rel=\"noopener\">the last tutorial<\/a>, we walked through simple steps to create a gadget using an Ajax DOM Object to consume the eXo API. However, you saw those steps outside the eXo Platform. I\u2019m sure you are eager to go deeper inside its working mechanism. The first topic I want to focus on is the eXo notification system. Yes, I said the first\u2014 we will focus on another topic in an upcoming tutorial. Let\u2019s get started!<br \/>\n<!--more--><br \/>\nThe eXo Platform provides a notification system that you can extend using two mechanisms:<\/p>\n<ul>\n<li>the channels of notification, such as email, directly online, through pushing, etc.; and<\/li>\n<li>the types of notifications, such as connection invitations, space activities, etc.<\/li>\n<\/ul>\n<p>This guide will show you how to use both of these mechanisms by:<\/p>\n<ul>\n<li>creating a new notification channel to push notification information to the console panel; and<\/li>\n<li>creating a new notification type to indicate when a user in your network changes his or her profile.<\/li>\n<\/ul>\n<p>You can use the steps below to create a complete extension with these features.<\/p>\n<p>1. Create a new Maven project as shown below:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_whole_structure.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-8921\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_whole_structure.png\" alt=\"notif_whole_structure\" width=\"299\" height=\"91\"><\/a><\/p>\n<p>2. Add the following dependencies to the <span class=\"navCode\">pom.xml file:<\/span><\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"https:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchemainstance\"\nxsi:schemaLocation=\"https:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n    &lt;groupId&gt;com.acme.samples&lt;\/groupId&gt;\n    &lt;artifactId&gt;console-notification&lt;\/artifactId&gt;\n    &lt;version&gt;1.0.0&lt;\/version&gt;\n    &lt;packaging&gt;pom&lt;\/packaging&gt;\n    &lt;modules&gt;\n        &lt;module&gt;lib&lt;\/module&gt;\n        &lt;module&gt;config&lt;\/module&gt;\n        &lt;module&gt;webapp&lt;\/module&gt;\n    &lt;\/modules&gt;\n    &lt;properties&gt;\n        &lt;org.exoplatform.depmgt.version&gt;10-SNAPSHOT&lt;\/org.exoplatform.depmgt.version&gt;\n        &lt;org.exoplatform.kernel.version&gt;2.4.9-GA&lt;\/org.exoplatform.kernel.version&gt;\n        &lt;org.exoplatform.core.version&gt;2.5.9-GA&lt;\/org.exoplatform.core.version&gt;\n        &lt;!-- GateIn Project Dependencies --&gt;\n        &lt;org.gatein.portal.version&gt;3.5.10.Final&lt;\/org.gatein.portal.version&gt;\n        &lt;!-- Platform Project Dependencies --&gt;\n        &lt;org.exoplatform.social.version&gt;4.2.x-SNAPSHOT&lt;\/org.exoplatform.social.version&gt;\n    &lt;\/properties&gt;\n    &lt;dependencyManagement&gt;\n        &lt;dependencies&gt;\n            &lt;!-- Import versions from platform project --&gt;\n            &lt;dependency&gt;\n                &lt;groupId&gt;org.exoplatform&lt;\/groupId&gt;\n                &lt;artifactId&gt;maven-depmgt-pom&lt;\/artifactId&gt;\n                &lt;version&gt;${org.exoplatform.depmgt.version}&lt;\/version&gt;\n                &lt;type&gt;pom&lt;\/type&gt;\n                &lt;scope&gt;import&lt;\/scope&gt;\n            &lt;\/dependency&gt;\n            &lt;dependency&gt;\n                &lt;groupId&gt;org.exoplatform.social&lt;\/groupId&gt;\n                &lt;artifactId&gt;social&lt;\/artifactId&gt;\n                &lt;version&gt;${org.exoplatform.social.version}&lt;\/version&gt;\n                &lt;type&gt;pom&lt;\/type&gt;\n                &lt;scope&gt;import&lt;\/scope&gt;\n            &lt;\/dependency&gt;\n            &lt;!-- Our own project modules --&gt;\n            &lt;dependency&gt;\n                &lt;groupId&gt;org.exoplatform.social&lt;\/groupId&gt;\n                &lt;artifactId&gt;social-notification-addon-webapp&lt;\/artifactId&gt;\n                &lt;version&gt;${project.version}&lt;\/version&gt;\n            &lt;\/dependency&gt;\n            &lt;dependency&gt;\n                &lt;groupId&gt;org.exoplatform.social&lt;\/groupId&gt;\n                &lt;artifactId&gt;social-notification-addon-lib&lt;\/artifactId&gt;\n                &lt;version&gt;${project.version}&lt;\/version&gt;\n            &lt;\/dependency&gt;\n            &lt;!-- To be replaced by an import of GateIn Portal parent POM --&gt;\n            &lt;dependency&gt;\n                &lt;groupId&gt;org.gatein.portal&lt;\/groupId&gt;\n                &lt;artifactId&gt;exo.portal.component.portal&lt;\/artifactId&gt;\n                &lt;version&gt;${org.gatein.portal.version}&lt;\/version&gt;\n            &lt;\/dependency&gt;\n        &lt;\/dependencies&gt;\n    &lt;\/dependencyManagement&gt;\n&lt;\/project&gt;<\/pre>\n<p>3. Create a <span class=\"navCode\">pom.xml<\/span> file and two <span class=\"navCode\">configuration.xml<\/span> files inside the config folder as shown below:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_config_structure.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-8922\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_config_structure.png\" alt=\"notif_config_structure\" width=\"351\" height=\"146\"><\/a><\/p>\n<p>4. Add the following information to <span class=\"navCode\">config\/pom.xml<\/span>:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"https:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchemainstance\"\nxsi:schemaLocation=\"https:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n    &lt;parent&gt;\n        &lt;groupId&gt;com.acme.samples&lt;\/groupId&gt;\n        &lt;artifactId&gt;console-notification&lt;\/artifactId&gt;\n        &lt;version&gt;1.0.0&lt;\/version&gt;\n    &lt;\/parent&gt;\n    &lt;artifactId&gt;console-notification-config&lt;\/artifactId&gt;\n    &lt;packaging&gt;jar&lt;\/packaging&gt;\n    &lt;build&gt;\n        &lt;finalName&gt;console-notification-config&lt;\/finalName&gt;\n    &lt;\/build&gt;\n&lt;\/project&gt;<\/pre>\n<p>5. Add the configurations below to <span class=\"navCode\">conf\/configuration.xml<\/span>:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;configuration\nxmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\"\nxsi:schemaLocation=\"https:\/\/www.exoplatform.org\/xml\/ns\/kernel_1_2.xsd https:\/\/www.exoplatform.org\/xml\/ns\/kernel_1_2.xsd\"\nxmlns=\"https:\/\/www.exoplatform.org\/xml\/ns\/kernel_1_2.xsd\"&gt;\n    &lt;external-component-plugins&gt;\n        &lt;!-- The full qualified name of the PortalContainerConfig --&gt;\n        &lt;target-component&gt;org.exoplatform.container.definition.PortalContainerConfig&lt;\/target-component&gt;\n        &lt;component-plugin&gt;\n            &lt;!-- The name of the plugin --&gt;\n            &lt;name&gt;Add PortalContainer Definitions&lt;\/name&gt;\n            &lt;!-- The name of the method to call on the PortalContainerConfig in order to register the PortalContainerDefinitions --&gt;\n            &lt;set-method&gt;registerChangePlugin&lt;\/set-method&gt;\n            &lt;!-- The full qualified name of the PortalContainerDefinitionPlugin --&gt;\n            &lt;type&gt;org.exoplatform.container.definition.PortalContainerDefinitionChangePlugin&lt;\/type&gt;\n            &lt;priority&gt;102&lt;\/priority&gt;\n            &lt;init-params&gt;\n                &lt;values-param&gt;\n                    &lt;name&gt;apply.specific&lt;\/name&gt;\n                    &lt;value&gt;portal&lt;\/value&gt;\n                &lt;\/values-param&gt;\n                &lt;object-param&gt;\n                    &lt;name&gt;addDependencies&lt;\/name&gt;\n                    &lt;object type=\"org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependencies\"&gt;\n                        &lt;!-- The name of the portal container --&gt;\n                        &lt;field name=\"dependencies\"&gt;\n                            &lt;collection type=\"java.util.ArrayList\"&gt;\n                                &lt;value&gt;\n                                    &lt;string&gt;console-notification-webapp&lt;\/string&gt;\n                                &lt;\/value&gt;\n                            &lt;\/collection&gt;\n                        &lt;\/field&gt;\n                    &lt;\/object&gt;\n                &lt;\/object-param&gt;\n            &lt;\/init-params&gt;\n        &lt;\/component-plugin&gt;\n    &lt;\/external-component-plugins&gt;\n&lt;\/configuration&gt;<\/pre>\n<p>6. Add the following configurations to <span class=\"navCode\">portal\/configuration.xml<\/span>:<\/p>\n<pre class=\"lang:default decode:true\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;configuration xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\"\nxsi:schemaLocation=\"https:\/\/www.exoplatform.org\/xml\/ns\/kernel_1_2.xsd https:\/\/www.exoplatform.org\/xml\/ns\/kernel_1_2.xsd\"\nxmlns=\"https:\/\/www.exoplatform.org\/xml\/ns\/kernel_1_2.xsd\"&gt;\n    &lt;!-- register new event listener --&gt;\n    &lt;external-component-plugins&gt;\n        &lt;target-component&gt;org.exoplatform.social.core.manager.IdentityManager&lt;\/target-component&gt;\n        &lt;component-plugin&gt;\n            &lt;name&gt;SocialProfileListener&lt;\/name&gt;\n            &lt;set-method&gt;registerProfileListener&lt;\/set-method&gt;\n            &lt;type&gt;com.acme.samples.notification.SocialProfileListener&lt;\/type&gt;\n        &lt;\/component-plugin&gt;\n    &lt;\/external-component-plugins&gt;\n    &lt;!-- register new channel --&gt;\n    &lt;external-component-plugins&gt;\n        &lt;target-component&gt;org.exoplatform.commons.api.notification.channel.ChannelManager&lt;\/target-component&gt;\n        &lt;component-plugin profiles=\"all\"&gt;\n            &lt;name&gt;console.channel&lt;\/name&gt;\n            &lt;set-method&gt;register&lt;\/set-method&gt;\n            &lt;type&gt;com.acme.samples.notification.ConsoleChannel&lt;\/type&gt;\n            &lt;description&gt;Register the console channel to manager.&lt;\/description&gt;\n        &lt;\/component-plugin&gt;\n    &lt;\/external-component-plugins&gt;\n    &lt;!-- register new notification type --&gt;\n    &lt;external-component-plugins&gt;\n        &lt;target-component&gt;org.exoplatform.commons.api.notification.service.setting.PluginContainer&lt;\/target-component&gt;\n        &lt;component-plugin&gt;\n            &lt;name&gt;notification.plugins&lt;\/name&gt;\n            &lt;set-method&gt;addPlugin&lt;\/set-method&gt;\n            &lt;type&gt;com.acme.samples.notification.plugin.UpdateProfilePlugin&lt;\/type&gt;\n            &lt;description&gt;Initial information for plugin.&lt;\/description&gt;\n            &lt;init-params&gt;\n                &lt;object-param&gt;\n                    &lt;name&gt;template.UpdateProfilePlugin&lt;\/name&gt;\n                    &lt;description&gt;The template of UpdateProfilePlugin&lt;\/description&gt;\n                    &lt;object\n                    type=\"org.exoplatform.commons.api.notification.plugin.config.PluginConfig\"&gt;\n                        &lt;field name=\"pluginId\"&gt;\n                            &lt;string&gt;UpdateProfilePlugin&lt;\/string&gt;\n                        &lt;\/field&gt;\n                        &lt;field name=\"resourceBundleKey\"&gt;\n                            &lt;string&gt;UINotification.label.UpdateProfilePlugin&lt;\/string&gt;\n                        &lt;\/field&gt;\n                        &lt;field name=\"order\"&gt;\n                            &lt;string&gt;11&lt;\/string&gt;\n                        &lt;\/field&gt;\n                        &lt;field name=\"defaultConfig\"&gt;\n                            &lt;collection type=\"java.util.ArrayList\"&gt;\n                                &lt;value&gt;\n                                    &lt;string&gt;Instantly&lt;\/string&gt;\n                                &lt;\/value&gt;\n                            &lt;\/collection&gt;\n                        &lt;\/field&gt;\n                        &lt;field name=\"groupId\"&gt;\n                            &lt;string&gt;general&lt;\/string&gt;\n                        &lt;\/field&gt;\n                        &lt;field name=\"bundlePath\"&gt;\n                            &lt;string&gt;locale.notification.template.Notification&lt;\/string&gt;\n                        &lt;\/field&gt;\n                    &lt;\/object&gt;\n                &lt;\/object-param&gt;\n            &lt;\/init-params&gt;\n        &lt;\/component-plugin&gt;\n    &lt;\/external-component-plugins&gt;\n&lt;\/configuration&gt;<\/pre>\n<p>This file does the following:<\/p>\n<ul>\n<li>Registers <span class=\"navCode\">SocialProfileListener<\/span> as a profile event listener plugin with the <span class=\"navCode\">IdentityManager<\/span> component. This plugin listens to user profile updating events.<\/li>\n<li>Registers the new <span class=\"navCode\">console.channel<\/span> plugin with the <span class=\"navCode\">ChannelManager<\/span> component. This plugin pushes notifications to the console panel.<\/li>\n<li>Registers the new <span class=\"navCode\">UpdateProfilePlugin<\/span> with the <span class=\"navCode\">PluginContainer<\/span> component. This plugin declares and initializes parameters for the new notification type. The initial parameters include the following:<br \/>\n\u2013 <span class=\"navCode\">template.UpdateProfilePlugin<\/span>\u2014the template for <span class=\"navCode\">UpdateProfilePlugin<\/span><br \/>\n\u2013 <span class=\"navCode\">pluginId<\/span>\u2014the ID of the plugin defined in the class <span class=\"navCode\">UpdateProfilePlugin<\/span><br \/>\n\u2013 <span class=\"navCode\">resourceBundleKey<\/span>\u2014the key that will be provided in the resource bundle files for each locale<br \/>\n\u2013 <span class=\"navCode\">order<\/span>\u2014the order in which the new type will be displayed in the notification group<br \/>\n\u2013 <span class=\"navCode\">groupId<\/span>\u2014the ID of the group this notification type belongs to<br \/>\n\u2013 <span class=\"navCode\">bundlePath<\/span>\u2014the path to the local resource<br \/>\n\u2013 <span class=\"navCode\">defaultConfig<\/span>\u2014the default settings for this notification type at start up<\/li>\n<\/ul>\n<p>7. Create another project under the <span class=\"navCode\">lib<\/span> folder with the <span class=\"navCode\">xml<\/span> file as shown below:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-8923\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure.png\" alt=\"notif_lib_structure\" width=\"352\" height=\"150\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure.png 352w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure-300x128.png 300w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure-200x85.png 200w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure-100x43.png 100w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_lib_structure-70x30.png 70w\" sizes=\"(max-width: 352px) 100vw, 352px\" \/><\/a><\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"https:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchemainstance\"\nxsi:schemaLocation=\"https:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n    &lt;parent&gt;\n        &lt;groupId&gt;com.acme.samples&lt;\/groupId&gt;\n        &lt;artifactId&gt;console-notification&lt;\/artifactId&gt;\n        &lt;version&gt;1.0.0&lt;\/version&gt;\n    &lt;\/parent&gt;\n    &lt;artifactId&gt;console-notification-lib&lt;\/artifactId&gt;\n    &lt;packaging&gt;jar&lt;\/packaging&gt;\n    &lt;dependencies&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;log4j&lt;\/groupId&gt;\n            &lt;artifactId&gt;log4j&lt;\/artifactId&gt;\n            &lt;scope&gt;provided&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.exoplatform.social&lt;\/groupId&gt;\n            &lt;artifactId&gt;social-component-core&lt;\/artifactId&gt;\n            &lt;scope&gt;provided&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.exoplatform.core&lt;\/groupId&gt;\n            &lt;artifactId&gt;exo.core.component.organization.api&lt;\/artifactId&gt;\n            &lt;scope&gt;provided&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.exoplatform.social&lt;\/groupId&gt;\n            &lt;artifactId&gt;social-component-common&lt;\/artifactId&gt;\n            &lt;scope&gt;provided&lt;\/scope&gt;\n        &lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n    &lt;build&gt;\n        &lt;finalName&gt;console-notification-lib&lt;\/finalName&gt;\n    &lt;\/build&gt;\n&lt;\/project&gt;<\/pre>\n<p>8. Implement the class <span class=\"navCode\">UpdateProfilePlugin.java<\/span> as follows:<\/p>\n<pre class=\"lang:default decode:true \">package com.acme.samples.notification.plugin;\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.Set;\nimport org.exoplatform.commons.api.notification.NotificationContext;\nimport org.exoplatform.commons.api.notification.model.ArgumentLiteral;\nimport org.exoplatform.commons.api.notification.model.NotificationInfo;\nimport org.exoplatform.commons.api.notification.plugin.BaseNotificationPlugin;\nimport org.exoplatform.commons.utils.CommonsUtils;\nimport org.exoplatform.commons.utils.ListAccess;\nimport org.exoplatform.container.xml.InitParams;\nimport org.exoplatform.services.log.ExoLogger;\nimport org.exoplatform.services.log.Log;\nimport org.exoplatform.social.core.identity.model.Identity;\nimport org.exoplatform.social.core.identity.model.Profile;\nimport org.exoplatform.social.core.manager.RelationshipManager;\n\/\/This class extends BaseNotificationPlugin to push new notification type of profile updating event\npublic class UpdateProfilePlugin extends BaseNotificationPlugin {\n    public final static ArgumentLiteral&lt;Profile&gt; PROFILE = new ArgumentLiteral&lt;Profile&gt;(Profile.class, \"profile\");\n    private static final Log LOG = ExoLogger.getLogger(UpdateProfilePlugin.class);\n    public final static String ID = \"UpdateProfilePlugin\";\n    public UpdateProfilePlugin(InitParams initParams) {\n        super(initParams);\n    }\n    @Override\n    public String getId() {\n        return ID;\n    }\n    @Override\n    public boolean isValid(NotificationContext ctx) {\n        return true;\n    }\n    @Override\n    protected NotificationInfo makeNotification(NotificationContext ctx) {\n        Profile profile = ctx.value(PROFILE);\n        Set&lt;String&gt; receivers = new HashSet&lt;String&gt;();\n        RelationshipManager relationshipManager = CommonsUtils.getService(RelationshipManager.class);\n        Identity updatedIdentity = profile.getIdentity();\n        ListAccess&lt;Identity&gt; listAccess = relationshipManager.getConnections(updatedIdentity);\n        try {\n            Identity[] relationships = relationshipManager.getConnections(updatedIdentity).load(0, listAccess.getSize());\n            for(Identity i : relationships) {\n                receivers.add(i.getRemoteId());\n            }\n            } catch (Exception ex) {\n            LOG.error(ex.getMessage(), ex);\n        }\n        return NotificationInfo.instance()\n        .setFrom(updatedIdentity.getRemoteId())\n        .to(new ArrayList&lt;String&gt;(receivers))\n        .setTitle(updatedIdentity.getProfile().getFullName() + \" updated his\/her profile.&lt;br\/&gt;\")\n        .key(getId());\n    }\n}\n<\/pre>\n<ul>\n<li>This class extends the <span class=\"navCode\">BaseNotificationPlugin<\/span>, which retrieves information from the new notification type for the user profile updating event.<\/li>\n<li>The <span class=\"navCode\">makeNotification()<\/span> method was overridden to generate essential information for a notification.<\/li>\n<\/ul>\n<p>9. Implement the class <span class=\"navCode\">SocialProfileListener.java<\/span> as shown below:<\/p>\n<pre class=\"lang:default decode:true\">package com.acme.samples.notification;\nimport org.exoplatform.commons.api.notification.NotificationContext;\nimport org.exoplatform.commons.api.notification.model.PluginKey;\nimport org.exoplatform.commons.notification.impl.NotificationContextImpl;\nimport org.exoplatform.social.core.identity.model.Profile;\nimport org.exoplatform.social.core.profile.ProfileLifeCycleEvent;\nimport org.exoplatform.social.core.profile.ProfileListenerPlugin;\nimport com.acme.samples.notification.plugin.UpdateProfilePlugin;\n\/* This class extends ProfileListenerPlugin to trigger avatar\/experience updating events and plug them into UpdateProfilePlugin as notifications *\/\npublic class SocialProfileListener extends ProfileListenerPlugin {\n    @Override\n    public void avatarUpdated(ProfileLifeCycleEvent event) {\n        Profile profile = event.getProfile();\n        NotificationContext ctx = NotificationContextImpl.cloneInstance().append(UpdateProfilePlugin.PROFILE, profile);\n        ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(UpdateProfilePlugin.ID))).execute(ctx);\n    }\n    @Override\n    public void experienceSectionUpdated(ProfileLifeCycleEvent event) {\n        Profile profile = event.getProfile();\n        NotificationContext ctx = NotificationContextImpl.cloneInstance().append(UpdateProfilePlugin.PROFILE, profile);\n        ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(UpdateProfilePlugin.ID))).execute(ctx);\n    }\n    \/\/Abstract classes must be overridden\n    @Override\n    public void contactSectionUpdated(ProfileLifeCycleEvent event) {\n        Profile profile = event.getProfile();\n        NotificationContext ctx = NotificationContextImpl.cloneInstance().append(UpdateProfilePlugin.PROFILE, profile);\n        ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(UpdateProfilePlugin.ID))).execute(ctx);\n    }\n    @Override\n    public void createProfile(ProfileLifeCycleEvent event) {\n        Profile profile = event.getProfile();\n        NotificationContext ctx = NotificationContextImpl.cloneInstance().append(UpdateProfilePlugin.PROFILE, profile);\n        ctx.getNotificationExecutor().with(ctx.makeCommand(PluginKey.key(UpdateProfilePlugin.ID))).execute(ctx);\n    }\n}<\/pre>\n<p>This class extends the ProfileListenerPlugin to trigger user profile updating events and plug them into UpdateProfilePlugin as notifications. An instance of UpdateProfilePlugin will be used to generate and send messages to all notification channels.<\/p>\n<p>\u2013 <span class=\"navCode\">avatarUpdated()<\/span>\u2014trigger an avatar updating event<br \/>\n\u2013 <span class=\"navCode\">experienceSectionUpdated()<\/span>\u2014trigger a user experience updating event<br \/>\n\u2013 <span class=\"navCode\">contactSectionUpdated()<\/span>\u2014trigger a user contact information updating event<br \/>\n\u2013 <span class=\"navCode\">createProfile()<\/span>\u2014trigger a user profile creating event<\/p>\n<p>10. Implement the class <span class=\"navCode\">java<\/span> to obtain the following code:<\/p>\n<pre class=\"lang:default decode:true \">package com.acme.samples.notification;\nimport java.io.Writer;\nimport org.exoplatform.commons.api.notification.NotificationContext;\nimport org.exoplatform.commons.api.notification.channel.AbstractChannel;\nimport org.exoplatform.commons.api.notification.channel.template.AbstractTemplateBuilder;\nimport org.exoplatform.commons.api.notification.channel.template.TemplateProvider;\nimport org.exoplatform.commons.api.notification.model.ChannelKey;\nimport org.exoplatform.commons.api.notification.model.MessageInfo;\nimport org.exoplatform.commons.api.notification.model.NotificationInfo;\nimport org.exoplatform.commons.api.notification.model.PluginKey;\nimport org.exoplatform.commons.notification.lifecycle.SimpleLifecycle;\nimport org.exoplatform.services.log.ExoLogger;\nimport org.exoplatform.services.log.Log;\n\/\/This class extends AbstractChannel to define a new notification channel which sends messages through console panel\npublic class ConsoleChannel extends AbstractChannel {\n    private static final Log LOG = ExoLogger.getLogger(ConsoleChannel.class);\n    private final static String ID = \"CONSOLE_CHANNEL\";\n    private final ChannelKey key = ChannelKey.key(ID);\n    public ConsoleChannel() {\n        super(new SimpleLifecycle());\n    }\n    @Override\n    public String getId() {\n        return ID;\n    }\n    @Override\n    public ChannelKey getKey() {\n        return key;\n    }\n    @Override\n    public void dispatch(NotificationContext ctx, String userId) {\n        LOG.info(String.format(\"CONSOLE:: %s will be received the message from pluginId: %s\",\n        userId,\n        ctx.getNotificationInfo().getKey().getId()));\n    }\n    @Override\n    public void registerTemplateProvider(TemplateProvider provider) {}\n    @Override\n    protected AbstractTemplateBuilder getTemplateBuilderInChannel(PluginKey key) {\n        return new AbstractTemplateBuilder() {\n            @Override\n            protected MessageInfo makeMessage(NotificationContext ctx) {\n                return null;\n            }\n            @Override\n            protected boolean makeDigest(NotificationContext ctx, Writer writer) {\n                return false;\n            }\n        };\n    }\n    }<\/pre>\n<ul>\n<li>This concrete class extends <strong>AbstractChannel<\/strong> to define a new notification channel that sends messages to the console panel. Any new <strong>channel<\/strong> must implement this interface and use an external-component-plugin configuration to be registered in the <strong>ChannelManager<\/strong>.<\/li>\n<li>The <span class=\"navCode\">dispatch()<\/span> method was overridden to write notification contents to the console panel.<\/li>\n<\/ul>\n<p>11. Create a new Maven project inside the <span class=\"navCode\">webapp<\/span> folder with the following <span class=\"navCode\">pom.xml<\/span> file:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-8924\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure.png\" alt=\"notif_webapp_structure\" width=\"361\" height=\"157\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure.png 361w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure-300x130.png 300w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure-200x87.png 200w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure-100x43.png 100w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notif_webapp_structure-70x30.png 70w\" sizes=\"(max-width: 361px) 100vw, 361px\" \/><\/a><\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"https:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchemainstance\"\nxsi:schemaLocation=\"https:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n    &lt;parent&gt;\n        &lt;groupId&gt;com.acme.samples&lt;\/groupId&gt;\n        &lt;artifactId&gt;console-notification&lt;\/artifactId&gt;\n        &lt;version&gt;1.0.0&lt;\/version&gt;\n    &lt;\/parent&gt;\n    &lt;artifactId&gt;console-notification-webapp&lt;\/artifactId&gt;\n    &lt;packaging&gt;war&lt;\/packaging&gt;\n    &lt;build&gt;\n        &lt;finalName&gt;console-notification-webapp&lt;\/finalName&gt;\n    &lt;\/build&gt;\n&lt;\/project&gt;<\/pre>\n<p>12. Add the following configurations to <span class=\"navCode\">WEB-INF\/web.xml<\/span>:<\/p>\n<pre class=\"lang:default decode:true \">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;web-app version=\"3.0\"\nmetadata-complete=\"true\"\nxmlns=\"https:\/\/java.sun.com\/xml\/ns\/javaee\"\nxmlns:xsi=\"https:\/\/www.w3.org\/2001\/XMLSchema-instance\"\nxsi:schemaLocation=\"https:\/\/java.sun.com\/xml\/ns\/javaee https:\/\/java.sun.com\/xml\/ns\/javaee\/web-app_3_0.xsd\"&gt;\n    &lt;display-name&gt;console-notification-webapp&lt;\/display-name&gt;\n    &lt;filter&gt;\n        &lt;filter-name&gt;ResourceRequestFilter&lt;\/filter-name&gt;\n        &lt;filter-class&gt;org.exoplatform.portal.application.ResourceRequestFilter&lt;\/filter-class&gt;\n    &lt;\/filter&gt;\n    &lt;filter-mapping&gt;\n        &lt;filter-name&gt;ResourceRequestFilter&lt;\/filter-name&gt;\n        &lt;url-pattern&gt;\/*&lt;\/url-pattern&gt;\n    &lt;\/filter-mapping&gt;\n&lt;\/web-app&gt;<\/pre>\n<p>\u2013 <em>display-name<\/em> \u2014 must be the same as the context name of the portal extension<\/p>\n<p>13. Open the <span class=\"navCode\">Notification_en.properties<\/span> file and add this text:<\/p>\n<pre class=\"lang:default decode:true\">###########################################\n# UpdateProfilePlugin #\n###########################################\n# For UI\nUINotification.title.UpdateProfilePlugin= Someone updates profile\nUINotification.label.UpdateProfilePlugin= Someone updates profile\nUINotification.subject.UpdateProfilePlugin= updated the profile information.<\/pre>\n<p>This is an English-language resource bundle. The <span class=\"navCode\">UINotification.title.UpdateProfilePlugin<\/span> and <span class=\"navCode\">UINotification.label.UpdateProfilePlugin<\/span> values will be used to display the English name of the new notification type through the user interface.<\/p>\n<p>14. Go up to the parent project\u2019s folder and build the project using the <span class=\"navCode\">mvn clean install<\/span> command<\/p>\n<p>15. After successfully building the project, copy the generated jar and war files into the corresponding deployment folders in which you unpacked the eXo Platform installation.<\/p>\n<p>16. Start the eXo Platform, and you will see your new functions appear in <span class=\"navCode\">Notification Settings<\/span>:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notification_setting.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-8925\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/notification_setting.png\" alt=\"notification_setting\" width=\"529\" height=\"226\"><\/a><\/p>\n<p>Remember to enable notification plugins on the administrator account, and then test these functions by updating any user\u2019s avatar or experience. A message regarding this activity will be pushed to all notification channels, as shown below:<\/p>\n<p><a href=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-8926\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification.png\" alt=\"intranet_notification\" width=\"354\" height=\"151\" srcset=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification.png 354w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification-300x128.png 300w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification-200x85.png 200w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification-100x43.png 100w, https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2015\/06\/intranet_notification-70x30.png 70w\" sizes=\"(max-width: 354px) 100vw, 354px\" \/><\/a><\/p>\n<p>Alternatively, a message will be shown on the console for each user connecting with the above user, as shown below:<\/p>\n<p><span class=\"navCode\">James will receive the message from pluginId: UpdateProfilePlugin<\/span><\/p>\n<p>The source code used in this tutorial is available on github <a href=\"https:\/\/github.com\/lannt-exoer\/console-notification-demo\" target=\"_blank\" rel=\"noopener\">here<\/a>.<\/p>\n<p>Finally, I would like to thank the eXo DOC and SOC teams for their great comments!<\/p>\n<p>(This article was originally posted on my blog: <a href=\"https:\/\/lanbk52.wordpress.com\/2015\/05\/31\/how-to-extend-the-exo-notification-system\/\" class=\"broken_link\" target=\"_blank\" rel=\"noopener\">Lan Nguyen ~ Writing is sharing<\/a>.)<\/p>\n<p><b><a href=\"https:\/\/community.exoplatform.com\/portal\/dw\/\" target=\"_blank\" rel=\"noopener\">Join the eXo tribe<\/a> by registering for the community and get updates, tutorials, support, and access to the Platform and add-on downloads!<\/b><\/p>\n<p><!--begin adv-events--><\/p>\n<div class=\"adv-events\" style=\"background: #476fad;padding: 30px 20px;color: white\">\n<div class=\"media\">\n<div class=\"pull-right\"><a href=\"https:\/\/www.exoplatform.com\/contact-us\/?utm_source=BlogEn&amp;utm_medium=Blog&amp;utm_campaign=Content&amp;utm_content=cta\"><br \/>\n<img decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-6587 alignright\" src=\"https:\/\/www.exoplatform.com\/blog\/wp-content\/uploads\/2014\/02\/how-to-make-the-most-of-eXo-platform41.png\" alt=\"make-the-most-out-of-eXo-platform4\" width=\"161\" height=\"85\"><br \/>\n<\/a><\/div>\n<div class=\"media-body\">\n<h4 class=\"media-heading\">Make the most out of eXo Platform 4<\/h4>\n<p>Register to the next weekly live demo session and get a complete overview of what you can do with eXo Platform 4. <strong><a href=\"https:\/\/www.exoplatform.com\/contact-us\/?utm_source=BlogEn&amp;utm_medium=Blog&amp;utm_campaign=Content&amp;utm_content=link\">Reserve your seat now!<\/a><\/strong><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!--end adv-events--><\/p>\n","protected":false},"excerpt":{"rendered":"In the last tutorial, we walked through simple steps to create a gadget using an Ajax DOM Object to consume the eXo API. However, you saw those steps outside the eXo Platform. I\u2019m sure you are eager to go deeper inside its working mechanism. The first topic I want to focus on is the eXo [&hellip;]","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[699],"tags":[],"lang":"en","translations":{"en":37777},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/posts\/37777"}],"collection":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/comments?post=37777"}],"version-history":[{"count":0,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/posts\/37777\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/media?parent=37777"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/categories?post=37777"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.exoplatform.com\/blog\/wp-json\/wp\/v2\/tags?post=37777"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}