1 Added the repository to the initial-setup and pull-all scripts

2 Added notification service dependency to the gradle file
3 Created an instance of the notificationManager
4 Wrote the start and tear down methods
5 Created a listener class for the notificaiton service
6 Added a notification role and gave it customer read permission
7 Created a notification admin user for notification operations

 File changes to be committed:
        modified:   build.gradle
        modified:   scripts/Unix/initial-setup.sh
        modified:   scripts/Unix/pull-all.sh
        modified:   scripts/windows/initial-setup.bat
        modified:   scripts/windows/pull-all.bat
        modified:   src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java
        new file:   src/main/java/org/apache/fineract/cn/dev/listener/NotificationListener.java

diff --git a/build.gradle b/build.gradle
index 2bb5f04..b5ba9cf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -53,6 +53,7 @@
         kuelapcheques           : '0.1.0-BUILD-SNAPSHOT',
         fineractcnpayroll       : '0.1.0-BUILD-SNAPSHOT',
         fineractcngroup         : '0.1.0-BUILD-SNAPSHOT',
+        fineractcnnotification  : '0.1.0-BUILD-SNAPSHOT',
         frameworkapi            : '0.1.0-BUILD-SNAPSHOT',
         frameworklang           : '0.1.0-BUILD-SNAPSHOT',
         frameworktest           : '0.1.0-BUILD-SNAPSHOT',
@@ -110,6 +111,7 @@
             [group: 'org.apache.fineract.cn.cheques', name: 'api', version: versions.kuelapcheques],
             [group: 'org.apache.fineract.cn.payroll', name: 'api', version: versions.fineractcnpayroll],
             [group: 'org.apache.fineract.cn.group', name: 'api', version: versions.fineractcngroup],
+            [group: 'org.apache.fineract.cn.notification', name: 'api', version: versions.fineractcnnotification],
 
             [group: 'org.apache.fineract.cn.anubis', name: 'api', version: versions.frameworkanubis],
             [group: 'org.apache.fineract.cn.anubis', name: 'test', version: versions.frameworkanubis],
diff --git a/scripts/Unix/initial-setup.sh b/scripts/Unix/initial-setup.sh
index e55870a..06efa14 100755
--- a/scripts/Unix/initial-setup.sh
+++ b/scripts/Unix/initial-setup.sh
@@ -58,7 +58,7 @@
 # exit tools directory
 cd ..
 
-get_modules fineract-cn-anubis fineract-cn-identity fineract-cn-permitted-feign-client fineract-cn-provisioner fineract-cn-rhythm fineract-cn-template fineract-cn-office fineract-cn-customer fineract-cn-group fineract-cn-accounting fineract-cn-portfolio fineract-cn-deposit-account-management fineract-cn-cheques fineract-cn-payroll fineract-cn-teller fineract-cn-reporting
+get_modules fineract-cn-anubis fineract-cn-identity fineract-cn-permitted-feign-client fineract-cn-provisioner fineract-cn-rhythm fineract-cn-template fineract-cn-office fineract-cn-customer fineract-cn-group fineract-cn-accounting fineract-cn-portfolio fineract-cn-deposit-account-management fineract-cn-cheques fineract-cn-payroll fineract-cn-teller fineract-cn-reporting fineract-cn-notifications
 
 mkdir integration-tests
 cd integration-tests
diff --git a/scripts/Unix/pull-all.sh b/scripts/Unix/pull-all.sh
index 8559490..514daf5 100644
--- a/scripts/Unix/pull-all.sh
+++ b/scripts/Unix/pull-all.sh
@@ -46,7 +46,7 @@
 
 get_modules fineract-cn-anubis fineract-cn-identity fineract-cn-permitted-feign-client fineract-cn-provisioner fineract-cn-rhythm \
 fineract-cn-template fineract-cn-office fineract-cn-customer fineract-cn-group fineract-cn-accounting \
-fineract-cn-portfolio fineract-cn-deposit-account-management fineract-cn-cheques fineract-cn-payroll fineract-cn-teller fineract-cn-reporting
+fineract-cn-portfolio fineract-cn-deposit-account-management fineract-cn-cheques fineract-cn-payroll fineract-cn-teller fineract-cn-reporting fineract-cn-notifications
 
 (
 cd integration-tests
diff --git a/scripts/windows/initial-setup.bat b/scripts/windows/initial-setup.bat
index 74e2ae3..61c9224 100644
--- a/scripts/windows/initial-setup.bat
+++ b/scripts/windows/initial-setup.bat
@@ -258,6 +258,15 @@
 TIMEOUT /T 5
 cd ..
 
+REM initialize notifications
+git clone https://github.com/%githubAccount%/fineract-cn-notifications.git
+cd notifications
+git remote add upstream https://github.com/ebenezergraham/fineract-cn-notifications.git
+git checkout develop
+CALL gradlew publishToMavenLocal
+TIMEOUT /T 5
+cd ..
+
 mkdir integration-tests
 cd integration-tests
 
diff --git a/scripts/windows/pull-all.bat b/scripts/windows/pull-all.bat
index dc3799b..2a5b703 100644
--- a/scripts/windows/pull-all.bat
+++ b/scripts/windows/pull-all.bat
@@ -243,6 +243,15 @@
 TIMEOUT /T 5
 cd ..
 
+REM pull notifications
+cd notifications
+git checkout develop
+git pull upstream develop
+CALL gradlew publishToMavenLocal
+git push origin develop
+TIMEOUT /T 5
+cd ..
+
 cd integration-tests
 
 REM pull service-starter
diff --git a/src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java b/src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java
index 8995a2b..9d45750 100644
--- a/src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java
+++ b/src/main/java/org/apache/fineract/cn/dev/ServiceRunner.java
@@ -24,16 +24,14 @@
 import org.apache.fineract.cn.accounting.importer.AccountImporter;
 import org.apache.fineract.cn.accounting.importer.LedgerImporter;
 import org.apache.fineract.cn.anubis.api.v1.domain.AllowedOperation;
-import org.apache.fineract.cn.cheque.api.v1.client.ChequeManager;
+import org.apache.fineract.cn.api.config.EnableApiFactory;
+import org.apache.fineract.cn.api.context.AutoGuest;
+import org.apache.fineract.cn.api.context.AutoSeshat;
+import org.apache.fineract.cn.api.context.AutoUserContext;
+import org.apache.fineract.cn.api.util.ApiConstants;
+import org.apache.fineract.cn.api.util.ApiFactory;
 import org.apache.fineract.cn.cassandra.util.CassandraConnectorConstants;
-import org.apache.fineract.cn.mariadb.util.MariaDBConstants;
-import org.apache.fineract.cn.test.env.ExtraProperties;
-import org.apache.fineract.cn.test.listener.EnableEventRecording;
-import org.apache.fineract.cn.test.listener.EventRecorder;
-import org.apache.fineract.cn.test.servicestarter.ActiveMQForTest;
-import org.apache.fineract.cn.test.servicestarter.EurekaForTest;
-import org.apache.fineract.cn.test.servicestarter.IntegrationTestEnvironment;
-import org.apache.fineract.cn.test.servicestarter.Microservice;
+import org.apache.fineract.cn.cheque.api.v1.client.ChequeManager;
 import org.apache.fineract.cn.customer.api.v1.CustomerEventConstants;
 import org.apache.fineract.cn.customer.api.v1.client.CustomerManager;
 import org.apache.fineract.cn.deposit.api.v1.client.DepositAccountManager;
@@ -44,6 +42,9 @@
 import org.apache.fineract.cn.identity.api.v1.events.ApplicationPermissionUserEvent;
 import org.apache.fineract.cn.identity.api.v1.events.ApplicationSignatureEvent;
 import org.apache.fineract.cn.identity.api.v1.events.EventConstants;
+import org.apache.fineract.cn.lang.AutoTenantContext;
+import org.apache.fineract.cn.mariadb.util.MariaDBConstants;
+import org.apache.fineract.cn.notification.api.v1.client.NotificationManager;
 import org.apache.fineract.cn.office.api.v1.client.OrganizationManager;
 import org.apache.fineract.cn.payroll.api.v1.client.PayrollManager;
 import org.apache.fineract.cn.portfolio.api.v1.client.PortfolioManager;
@@ -53,13 +54,13 @@
 import org.apache.fineract.cn.rhythm.api.v1.client.RhythmManager;
 import org.apache.fineract.cn.rhythm.api.v1.events.BeatEvent;
 import org.apache.fineract.cn.teller.api.v1.client.TellerManager;
-import org.apache.fineract.cn.api.config.EnableApiFactory;
-import org.apache.fineract.cn.api.context.AutoGuest;
-import org.apache.fineract.cn.api.context.AutoSeshat;
-import org.apache.fineract.cn.api.context.AutoUserContext;
-import org.apache.fineract.cn.api.util.ApiConstants;
-import org.apache.fineract.cn.api.util.ApiFactory;
-import org.apache.fineract.cn.lang.AutoTenantContext;
+import org.apache.fineract.cn.test.env.ExtraProperties;
+import org.apache.fineract.cn.test.listener.EnableEventRecording;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.apache.fineract.cn.test.servicestarter.ActiveMQForTest;
+import org.apache.fineract.cn.test.servicestarter.EurekaForTest;
+import org.apache.fineract.cn.test.servicestarter.IntegrationTestEnvironment;
+import org.apache.fineract.cn.test.servicestarter.Microservice;
 import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
 import org.eclipse.aether.resolution.ArtifactResolutionException;
 import org.junit.*;
@@ -97,7 +98,11 @@
   private static final String ADMIN_USER_NAME = "antony";
   private static final String TEST_LOGGER = "test-logger";
   private static final String LOAN_INCOME_LEDGER = "1100";
-
+  
+  private static final String NOTIFICATION_USER_PASSWORD = "shingi";
+  private static final String NOTIFICATION_ROLE = "notificationAdmin";
+  private static final String NOTIFICATION_USER_IDENTIFIER = "wadaadmin";
+  
   private static Microservice<Provisioner> provisionerService;
   private static Microservice<IdentityManager> identityManager;
   private static Microservice<RhythmManager> rhythmManager;
@@ -111,8 +116,9 @@
   private static Microservice<ChequeManager> chequeManager;
   private static Microservice<PayrollManager> payrollManager;
   private static Microservice<GroupManager> groupManager;
-
-
+  private static Microservice<NotificationManager> notificationManager;
+  
+  
   private static DB embeddedMariaDb;
 
   private static final String CUSTOM_PROP_PREFIX = "custom.";
@@ -239,10 +245,14 @@
 
     ServiceRunner.groupManager = new Microservice<>(GroupManager.class, "group", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
     startService(generalProperties, ServiceRunner.groupManager);
+  
+    ServiceRunner.notificationManager = new Microservice<>(NotificationManager.class, "notification", "0.1.0-BUILD-SNAPSHOT", ServiceRunner.INTEGRATION_TEST_ENVIRONMENT);
+    startService(generalProperties, ServiceRunner.notificationManager);
   }
 
   @After
   public void tearDown() throws Exception {
+    ServiceRunner.notificationManager.kill();
     ServiceRunner.groupManager.kill();
     ServiceRunner.payrollManager.kill();
     ServiceRunner.chequeManager.kill();
@@ -286,6 +296,7 @@
     System.out.println("Cheque Service: " + ServiceRunner.chequeManager.getProcessEnvironment().serverURI());
     System.out.println("Payroll Service: " + ServiceRunner.payrollManager.getProcessEnvironment().serverURI());
     System.out.println("Group Service: " + ServiceRunner.groupManager.getProcessEnvironment().serverURI());
+    System.out.println("Notification Service: " + ServiceRunner.notificationManager.getProcessEnvironment().serverURI());
 
     boolean run = true;
 
@@ -349,7 +360,8 @@
         ApplicationBuilder.create(ServiceRunner.reportManager.name(), ServiceRunner.reportManager.uri()),
         ApplicationBuilder.create(ServiceRunner.chequeManager.name(), ServiceRunner.chequeManager.uri()),
         ApplicationBuilder.create(ServiceRunner.payrollManager.name(), ServiceRunner.payrollManager.uri()),
-        ApplicationBuilder.create(ServiceRunner.groupManager.name(), ServiceRunner.groupManager.uri())
+        ApplicationBuilder.create(ServiceRunner.groupManager.name(), ServiceRunner.groupManager.uri()),
+        ApplicationBuilder.create(ServiceRunner.notificationManager.name(), ServiceRunner.notificationManager.uri())
     );
 
 
@@ -454,9 +466,13 @@
       provisionApp(tenant, ServiceRunner.payrollManager, org.apache.fineract.cn.payroll.api.v1.EventConstants.INITIALIZE);
 
       provisionApp(tenant, ServiceRunner.groupManager, org.apache.fineract.cn.group.api.v1.EventConstants.INITIALIZE);
-
+  
+      provisionApp(tenant, ServiceRunner.notificationManager, org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants.INITIALIZE);
+  
       final UserWithPassword orgAdminUserPassword = createOrgAdminRoleAndUser(tenantAdminPassword.getAdminPassword());
-
+  
+      createNotificationsAdmin(tenantAdminPassword.getAdminPassword());
+  
       createChartOfAccounts(orgAdminUserPassword);
 
       return tenantAdminPassword.getAdminPassword();
@@ -615,6 +631,47 @@
 
     return role;
   }
+  
+  private UserWithPassword createNotificationsAdmin(final String tenantAdminPassword) throws InterruptedException {
+    final Authentication adminAuthentication;
+    try (final AutoUserContext ignored = new AutoGuest()) {
+      adminAuthentication = ServiceRunner.identityManager.api().login(ADMIN_USER_NAME, tenantAdminPassword);
+    }
+    
+    try (final AutoUserContext ignored = new AutoUserContext(ADMIN_USER_NAME, adminAuthentication.getAccessToken())) {
+      final Role notificationRole = defineNotificationRole();
+      
+      ServiceRunner.identityManager.api().createRole(notificationRole);
+      Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_POST_ROLE, notificationRole.getIdentifier()));
+      
+      final UserWithPassword notificationUser = new UserWithPassword();
+      notificationUser.setIdentifier(NOTIFICATION_USER_IDENTIFIER);
+      notificationUser.setPassword(Base64Utils.encodeToString(NOTIFICATION_USER_PASSWORD.getBytes()));
+      notificationUser.setRole(notificationRole.getIdentifier());
+      
+      ServiceRunner.identityManager.api().createUser(notificationUser);
+      Assert.assertTrue(this.eventRecorder.wait(EventConstants.OPERATION_POST_USER, notificationUser.getIdentifier()));
+      
+      ServiceRunner.identityManager.api().logout();
+      
+      enableUser(notificationUser);
+      return notificationUser;
+    }
+  }
+  
+  private Role defineNotificationRole() {
+    final Permission customerPermission = new Permission();
+    customerPermission.setAllowedOperations(Collections.singleton(AllowedOperation.READ));
+    customerPermission.setPermittableEndpointGroupIdentifier(org.apache.fineract.cn.customer.PermittableGroupIds.CUSTOMER);
+    
+    final Role role = new Role();
+    role.setIdentifier(NOTIFICATION_ROLE);
+    role.setPermissions(Arrays.asList(
+        customerPermission
+        )
+    );
+    return role;
+  }
 
   private void enableUser(final UserWithPassword userWithPassword) throws InterruptedException {
     final Authentication passwordOnlyAuthentication
diff --git a/src/main/java/org/apache/fineract/cn/dev/listener/NotificationListener.java b/src/main/java/org/apache/fineract/cn/dev/listener/NotificationListener.java
new file mode 100644
index 0000000..9c017f6
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/dev/listener/NotificationListener.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.dev.listener;
+
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class NotificationListener {
+
+  private final EventRecorder eventRecorder;
+
+  @Autowired
+  public NotificationListener(final EventRecorder eventRecorder) {
+    this.eventRecorder = eventRecorder;
+  }
+
+  @JmsListener(
+      subscription = NotificationEventConstants.DESTINATION,
+      destination = NotificationEventConstants.DESTINATION,
+      selector = NotificationEventConstants.SELECTOR_INITIALIZE
+  )
+  public void onInitialized(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+                            final String payload) {
+    this.eventRecorder.event(tenant, NotificationEventConstants.INITIALIZE, payload, String.class);
+  }
+}