You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by na...@apache.org on 2017/08/21 10:49:26 UTC

[3/4] fineract git commit: Added Notification Module

Added Notification Module

Added Notification Module

Added Notification Module

Added Notification Module

Added license file for jar analyzer

Added entry into LICENSE_RELEASE file

Added gradle wrapper


Project: http://git-wip-us.apache.org/repos/asf/fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/fineract/commit/c60c6601
Tree: http://git-wip-us.apache.org/repos/asf/fineract/tree/c60c6601
Diff: http://git-wip-us.apache.org/repos/asf/fineract/diff/c60c6601

Branch: refs/heads/develop
Commit: c60c6601c07df7903214fcfbbb1145741fc0ef42
Parents: 455ef98
Author: Adhyan <ad...@yahoo.com>
Authored: Tue Jan 3 14:24:30 2017 +0530
Committer: Adhyan <ad...@yahoo.com>
Committed: Sun Aug 20 21:21:24 2017 +0530

----------------------------------------------------------------------
 LICENSE_RELEASE                                 |   4 +
 fineract-provider/.gitignore                    |   1 +
 fineract-provider/dependencies.gradle           |   7 +-
 fineract-provider/dev-dependencies.gradle       |   6 +-
 .../integrationtests/NotificationApiTest.java   |  57 ++
 .../common/NotificationHelper.java              |  43 ++
 .../TenantAwareBasicAuthenticationFilter.java   |  13 +-
 .../api/NotificationApiResource.java            |  89 +++
 .../cache/CacheNotificationResponseHeader.java  |  50 ++
 .../notification/data/NotificationData.java     | 143 +++++
 .../data/NotificationMapperData.java            |  78 +++
 .../notification/domain/Notification.java       | 112 ++++
 .../notification/domain/NotificationMapper.java |  78 +++
 .../domain/NotificationMapperRepository.java    |  24 +
 .../domain/NotificationRepository.java          |  24 +
 .../NotificationEventListener.java              |  96 +++
 .../NotificationEventService.java               |  50 ++
 .../service/NotificationDomainService.java      |  23 +
 .../service/NotificationDomainServiceImpl.java  | 590 +++++++++++++++++++
 ...ificationGeneratorReadRepositoryWrapper.java |  35 ++
 ...ationGeneratorReadRepositoryWrapperImpl.java |  53 ++
 ...tificationGeneratorWritePlatformService.java |  27 +
 ...cationGeneratorWritePlatformServiceImpl.java |  41 ++
 ...NotificationMapperReadRepositoryWrapper.java |  34 ++
 ...ficationMapperReadRepositoryWrapperImpl.java |  53 ++
 .../NotificationMapperWritePlatformService.java |  27 +
 ...ificationMapperWritePlatformServiceImpl.java |  41 ++
 .../NotificationReadPlatformService.java        |  34 ++
 .../NotificationReadPlatformServiceImpl.java    | 219 +++++++
 .../NotificationWritePlatformService.java       |  29 +
 .../NotificationWritePlatformServiceImpl.java   | 129 ++++
 ...ntWritePlatformServiceJpaRepositoryImpl.java |   3 +
 .../BusinessEventNotificationConstants.java     |  14 +-
 ...esWritePlatformServiceJpaRepositoryImpl.java |  30 +-
 ...onWritePlatformServiceJpaRepositoryImpl.java |   2 +
 ...anWritePlatformServiceJpaRepositoryImpl.java |   3 +-
 ...ctWritePlatformServiceJpaRepositoryImpl.java |  19 +-
 ...ssWritePlatformServiceJpaRepositoryImpl.java |  27 +-
 ...ntWritePlatformServiceJpaRepositoryImpl.java |   8 +-
 ...ssWritePlatformServiceJpaRepositoryImpl.java |   6 +
 ...ntWritePlatformServiceJpaRepositoryImpl.java |  26 +-
 ...ctWritePlatformServiceJpaRepositoryImpl.java |  20 +-
 .../resources/META-INF/spring/appContext.xml    |   4 +
 .../META-INF/spring/notificationContext.xml     |  44 ++
 .../V334__notification_module_tables.sql        |  48 ++
 .../apache/fineract/notification/Listener.java  |  33 ++
 .../fineract/notification/ListenerTest.java     |  52 ++
 .../fineract/notification/SenderTest.java       |  77 +++
 .../fineract/notification/StorageTest.java      | 130 ++++
 .../META-INF/testNotificationContext.xml        |  52 ++
 licenses/binary/JarAnalyzer.BSD                 |  26 +
 51 files changed, 2810 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/LICENSE_RELEASE
----------------------------------------------------------------------
diff --git a/LICENSE_RELEASE b/LICENSE_RELEASE
index 8acc951..2c50915 100644
--- a/LICENSE_RELEASE
+++ b/LICENSE_RELEASE
@@ -300,4 +300,8 @@ This product bundles Backport Util Concurrent v3.1 written by Dawid Kurzyniec,
 which is avilable under Public Domain license. 
 For details see licenses/binary/Backport.PL
 
+This product bundles JarAnalyzer v1.2 written by Kirk Knoernschild,
+which is available under BSD license.
+For details see licences/binary/JarAnalyzer.BSD
+
 ******************************************
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/.gitignore
----------------------------------------------------------------------
diff --git a/fineract-provider/.gitignore b/fineract-provider/.gitignore
index 8e9e830..e4bae86 100644
--- a/fineract-provider/.gitignore
+++ b/fineract-provider/.gitignore
@@ -7,5 +7,6 @@ repos
 .settings
 .gradle
 *.log
+.idea
 !gradle/wrapper/gradle-wrapper.jar
 /gradle

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/dependencies.gradle
----------------------------------------------------------------------
diff --git a/fineract-provider/dependencies.gradle b/fineract-provider/dependencies.gradle
index f331016..562e767 100644
--- a/fineract-provider/dependencies.gradle
+++ b/fineract-provider/dependencies.gradle
@@ -91,11 +91,16 @@ dependencies {
                 [group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.5'],
                 // Once we've switched to Java 8 this dep can be removed.
                 //[group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.0']
+                [group: 'org.springframework', name:'spring-jms'],
+                [group: 'org.apache.activemq', name: 'activemq-broker']
+
      )
      testCompile 'junit:junit:4.11',
                  'junit:junit-dep:4.11',
                  'org.mockito:mockito-core:1.9.5',
                  'com.jayway.restassured:rest-assured:2.3.3',
-                 [group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion]
+                 [group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion],
+                 [group: 'com.mockrunner', name: 'mockrunner-jms', version: '1.0.6'],
+                 [group: 'com.mockrunner', name: 'mockrunner-jdbc', version: '1.0.6']
 
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/dev-dependencies.gradle
----------------------------------------------------------------------
diff --git a/fineract-provider/dev-dependencies.gradle b/fineract-provider/dev-dependencies.gradle
index 949b678..80c8f49 100644
--- a/fineract-provider/dev-dependencies.gradle
+++ b/fineract-provider/dev-dependencies.gradle
@@ -90,11 +90,15 @@ dependencies {
                 [group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.5'],
                 // Once we've switched to Java 8 this dep can be removed.
                 //[group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.0']
+                [group: 'org.springframework', name:'spring-jms'],
+                [group: 'org.apache.activemq', name: 'activemq-broker']
      )
      testCompile 'junit:junit:4.11',
                  'junit:junit-dep:4.11',
                  'org.mockito:mockito-core:1.9.5',
                  'com.jayway.restassured:rest-assured:2.3.3',
-                 [group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion]
+                 [group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion],
+                 [group: 'com.mockrunner', name: 'mockrunner-jms', version: '1.0.6'],
+                 [group: 'com.mockrunner', name: 'mockrunner-jdbc', version: '1.0.6']
 
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
new file mode 100644
index 0000000..c516502
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/NotificationApiTest.java
@@ -0,0 +1,57 @@
+package org.apache.fineract.integrationtests;
+
+/**
+ * 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.
+ */
+
+
+import com.jayway.restassured.builder.RequestSpecBuilder;
+import com.jayway.restassured.builder.ResponseSpecBuilder;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+import org.apache.fineract.integrationtests.common.NotificationHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+public class NotificationApiTest {
+
+    private ResponseSpecification responseSpec;
+    private RequestSpecification requestSpec;
+
+    @Before
+    public void setUp() {
+        Utils.initializeRESTAssured();
+        this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build();
+        this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+        this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testNotificationRetrieval() {
+        HashMap<String, Object> response = (HashMap<String, Object>) NotificationHelper.getNotifications(this.requestSpec,
+                this.responseSpec, "");
+        System.out.println("Response : " + response.toString());
+        Assert.assertNotNull(response);
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
new file mode 100644
index 0000000..efac104
--- /dev/null
+++ b/fineract-provider/src/integrationTest/java/org/apache/fineract/integrationtests/common/NotificationHelper.java
@@ -0,0 +1,43 @@
+package org.apache.fineract.integrationtests.common;
+
+/**
+ * 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.
+ */
+
+import com.jayway.restassured.specification.RequestSpecification;
+import com.jayway.restassured.specification.ResponseSpecification;
+
+public class NotificationHelper {
+
+    private final RequestSpecification requestSpec;
+    private final ResponseSpecification responseSpec;
+
+    private static final String NOTIFICATION_API_URL = "/fineract-provider/api/v1/notifications?" + Utils.TENANT_IDENTIFIER;
+
+    public NotificationHelper(RequestSpecification requestSpec, ResponseSpecification responseSpec) {
+        this.requestSpec = requestSpec;
+        this.responseSpec = responseSpec;
+    }
+
+    public static Object getNotifications(final RequestSpecification requestSpec, final ResponseSpecification responseSpec,
+                                          final String jsonReturn) {
+        final String GET_NOTIFICATIONS_URL = NOTIFICATION_API_URL;
+        System.out.println("-----------------------------GET NOTIFICATIONS-----------------------------------");
+        return Utils.performServerGet(requestSpec, responseSpec, GET_NOTIFICATIONS_URL, "");
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
index abe243e..a36079d 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/filter/TenantAwareBasicAuthenticationFilter.java
@@ -37,6 +37,7 @@ import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
 import org.apache.fineract.infrastructure.security.data.PlatformRequestLog;
 import org.apache.fineract.infrastructure.security.exception.InvalidTenantIdentiferException;
 import org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
+import org.apache.fineract.notification.service.NotificationReadPlatformService;
 import org.apache.fineract.useradministration.domain.AppUser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -77,7 +78,7 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
     private final ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer;
     private final ConfigurationDomainService configurationDomainService;
     private final CacheWritePlatformService cacheWritePlatformService;
-
+    private final NotificationReadPlatformService notificationReadPlatformService;
     private final String tenantRequestHeader = "Fineract-Platform-TenantId";
     private final boolean exceptionIfHeaderMissing = true;
 
@@ -85,12 +86,14 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
     public TenantAwareBasicAuthenticationFilter(final AuthenticationManager authenticationManager,
             final AuthenticationEntryPoint authenticationEntryPoint, final BasicAuthTenantDetailsService basicAuthTenantDetailsService,
             final ToApiJsonSerializer<PlatformRequestLog> toApiJsonSerializer, final ConfigurationDomainService configurationDomainService,
-            final CacheWritePlatformService cacheWritePlatformService) {
+            final CacheWritePlatformService cacheWritePlatformService,
+            final NotificationReadPlatformService notificationReadPlatformService) {
         super(authenticationManager, authenticationEntryPoint);
         this.basicAuthTenantDetailsService = basicAuthTenantDetailsService;
         this.toApiJsonSerializer = toApiJsonSerializer;
         this.configurationDomainService = configurationDomainService;
         this.cacheWritePlatformService = cacheWritePlatformService;
+        this.notificationReadPlatformService = notificationReadPlatformService;
     }
 
     @Override
@@ -167,6 +170,12 @@ public class TenantAwareBasicAuthenticationFilter extends BasicAuthenticationFil
     		throws IOException {
     	super.onSuccessfulAuthentication(request, response, authResult);
 		AppUser user = (AppUser) authResult.getPrincipal();
+
+        if (notificationReadPlatformService.hasUnreadNotifications(user.getId())) {
+            response.addHeader("X-Notification-Refresh", "true");
+        } else {
+            response.addHeader("X-Notification-Refresh", "false");
+        }
 		
 		String pathURL = request.getRequestURI();
 		boolean isSelfServiceRequest = (pathURL != null && pathURL.contains("/self/"));

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
new file mode 100644
index 0000000..065d7cb
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/api/NotificationApiResource.java
@@ -0,0 +1,89 @@
+/**
+ * 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.notification.api;
+
+
+import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
+import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
+import org.apache.fineract.infrastructure.core.serialization.ToApiJsonSerializer;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.notification.data.NotificationData;
+import org.apache.fineract.notification.service.NotificationReadPlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+
+@Path("/notifications")
+@Component
+@Scope("singleton")
+public class NotificationApiResource {
+
+    private final PlatformSecurityContext context;
+    private final NotificationReadPlatformService notificationReadPlatformService;
+    private final ApiRequestParameterHelper apiRequestParameterHelper;
+    private final ToApiJsonSerializer<NotificationData> toApiJsonSerializer;
+
+    @Autowired
+    public NotificationApiResource(PlatformSecurityContext context,
+                                   NotificationReadPlatformService notificationReadPlatformService,
+                                   ApiRequestParameterHelper apiRequestParameterHelper,
+                                   ToApiJsonSerializer<NotificationData> toApiJsonSerializer) {
+        this.context = context;
+        this.notificationReadPlatformService = notificationReadPlatformService;
+        this.apiRequestParameterHelper = apiRequestParameterHelper;
+        this.toApiJsonSerializer = toApiJsonSerializer;
+    }
+
+    @GET
+    @Consumes({MediaType.APPLICATION_JSON})
+    @Produces({MediaType.APPLICATION_JSON})
+    public String getAllNotifications(@Context final UriInfo uriInfo, @QueryParam("orderBy") final String orderBy,
+                                            @QueryParam("limit") final Integer limit,
+                                            @QueryParam("offset") final Integer offset,
+                                            @QueryParam("sortOrder") final String sortOrder,
+                                            @QueryParam("isRead") final boolean isRead) {
+
+        this.context.authenticatedUser();
+        final Page<NotificationData> notificationData;
+        final SearchParameters searchParameters = SearchParameters.forPagination(offset, limit, orderBy, sortOrder);
+        if (!isRead) {
+            notificationData = this.notificationReadPlatformService.getAllUnreadNotifications(searchParameters);
+        } else {
+            notificationData = this.notificationReadPlatformService.getAllNotifications(searchParameters);
+        }
+        final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper
+                .process(uriInfo.getQueryParameters());
+        return this.toApiJsonSerializer.serialize(settings, notificationData);
+    }
+
+    @PUT
+    @Consumes({MediaType.APPLICATION_JSON})
+    @Produces({MediaType.APPLICATION_JSON})
+    public void update() {
+        this.context.authenticatedUser();
+        this.notificationReadPlatformService.updateNotificationReadStatus();
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java b/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
new file mode 100644
index 0000000..205050b
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/cache/CacheNotificationResponseHeader.java
@@ -0,0 +1,50 @@
+/**
+ * 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.notification.cache;
+
+
+public class CacheNotificationResponseHeader {
+
+    private boolean hasNotifications;
+    private Long lastFetch;
+
+    public CacheNotificationResponseHeader() {
+    }
+
+    public CacheNotificationResponseHeader(boolean hasNotifications, Long lastFetch) {
+        this.hasNotifications = hasNotifications;
+        this.lastFetch = lastFetch;
+    }
+
+    public boolean hasNotifications() {
+        return hasNotifications;
+    }
+
+    public void setHasNotifications(boolean hasNotifications) {
+        this.hasNotifications = hasNotifications;
+    }
+
+    public Long getLastFetch() {
+        return lastFetch;
+    }
+
+    public void setLastFetch(Long lastFetch) {
+        this.lastFetch = lastFetch;
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java b/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
new file mode 100644
index 0000000..63dab1a
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationData.java
@@ -0,0 +1,143 @@
+/**
+ * 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.notification.data;
+
+import java.io.Serializable;
+import java.util.List;
+
+public class NotificationData implements Serializable {
+
+    private Long id;
+    private String objectType;
+    private Long objectId;
+    private String action;
+    private Long actorId;
+    private String content;
+    private boolean isSystemGenerated;
+    private String tenantIdentifier;
+    private String createdAt;
+    private Long officeId;
+    private List<Long> userIds;
+
+    public NotificationData() {
+
+    }
+
+    public NotificationData(String objectType, Long objectId, String action, Long actorId, String content, boolean isSystemGenerated,
+                            String tenantIdentifier, Long officeId, List<Long> userIds) {
+        this.objectType = objectType;
+        this.objectId = objectId;
+        this.action = action;
+        this.actorId = actorId;
+        this.content = content;
+        this.isSystemGenerated = isSystemGenerated;
+        this.tenantIdentifier = tenantIdentifier;
+        this.officeId = officeId;
+        this.userIds = userIds;
+    }
+
+    public Long getOfficeId() {
+        return officeId;
+    }
+
+    public void setOfficeId(Long officeId) {
+        this.officeId = officeId;
+    }
+
+    public List<Long> getUserIds() {
+        return userIds;
+    }
+
+    public void setUserId(List<Long> userIds) {
+        this.userIds = userIds;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(String createdAt) {
+        this.createdAt = createdAt;
+    }
+
+    public String getObjectType() {
+        return objectType;
+    }
+
+    public void setObjectType(String objectType) {
+        this.objectType = objectType;
+    }
+
+    public Long getObjectIdentfier() {
+        return objectId;
+    }
+
+    public void entifier(Long objectIdentifier) {
+        this.objectId = objectIdentifier;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public Long getActor() {
+        return actorId;
+    }
+
+    public void setActor(Long actorId) {
+        this.actorId = actorId;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public boolean isSystemGenerated() {
+        return isSystemGenerated;
+    }
+
+    public void setSystemGenerated(boolean systemGenerated) {
+        isSystemGenerated = systemGenerated;
+    }
+
+    public String getTenantIdentifier() {
+        return tenantIdentifier;
+    }
+
+    public void setTenantIdentifier(String tenantIdentifier) {
+        this.tenantIdentifier = tenantIdentifier;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationMapperData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationMapperData.java b/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationMapperData.java
new file mode 100644
index 0000000..659fb5f
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/data/NotificationMapperData.java
@@ -0,0 +1,78 @@
+/**
+ * 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.notification.data;
+
+public class NotificationMapperData {
+
+    private Long id;
+    private Long notificationId;
+    private Long userId;
+    private boolean isRead;
+    private String createdAt;
+
+    public NotificationMapperData(Long id, Long notificationId, Long userId, boolean isRead, String createdAt) {
+        this.id = id;
+        this.notificationId = notificationId;
+        this.userId = userId;
+        this.isRead = isRead;
+        this.createdAt = createdAt;
+    }
+
+    public NotificationMapperData() {}
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getNotificationId() {
+        return notificationId;
+    }
+
+    public void setNotificationId(Long notificationId) {
+        this.notificationId = notificationId;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public boolean isRead() {
+        return isRead;
+    }
+
+    public void setRead(boolean read) {
+        isRead = read;
+    }
+
+    public String getCreatedAt() {
+        return createdAt;
+    }
+
+    public void setCreatedAt(String createdAt) {
+        this.createdAt = createdAt;
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
new file mode 100644
index 0000000..cf7d41e
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/Notification.java
@@ -0,0 +1,112 @@
+/**
+ * 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.notification.domain;
+
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "notification_generator")
+public class Notification extends AbstractPersistableCustom<Long> {
+
+    @Column(name = "object_type")
+    private String objectType;
+
+    @Column(name = "object_identifier")
+    private Long objectIdentifier;
+
+    @Column(name = "action")
+    private String action;
+
+    @Column(name = "actor")
+    private Long actorId;
+
+    @Column(name = "is_system_generated")
+    private boolean isSystemGenerated;
+
+    @Column(name = "notification_content")
+    private String notificationContent;
+
+    @Column(name = "created_at")
+    private String createdAt;
+
+    public Notification() {}
+
+    public Notification(String objectType, Long objectIdentifier, String action, Long actorId, boolean isSystemGenerated,
+                        String notificationContent, String createdAt) {
+        this.objectType = objectType;
+        this.objectIdentifier = objectIdentifier;
+        this.action = action;
+        this.actorId = actorId;
+        this.isSystemGenerated = isSystemGenerated;
+        this.notificationContent = notificationContent;
+        this.createdAt = createdAt;
+    }
+
+    public String getObjectType() {
+        return objectType;
+    }
+
+    public void setObjectType(String objectType) {
+        this.objectType = objectType;
+    }
+
+    public Long getObjectIdentifier() {
+        return objectIdentifier;
+    }
+
+    public void setObjectIdentifier(Long objectIdentifier) {
+        this.objectIdentifier = objectIdentifier;
+    }
+
+    public String getAction() {
+        return action;
+    }
+
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    public Long getActor() {
+        return actorId;
+    }
+
+    public void setActor(Long actor) {
+        this.actorId = actorId;
+    }
+
+    public boolean isSystemGenerated() {
+        return isSystemGenerated;
+    }
+
+    public void setSystemGenerated(boolean systemGenerated) {
+        isSystemGenerated = systemGenerated;
+    }
+
+    public String getNotificationContent() {
+        return notificationContent;
+    }
+
+    public void setNotificationContent(String notificationContent) {
+        this.notificationContent = notificationContent;
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
new file mode 100644
index 0000000..5297d23
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapper.java
@@ -0,0 +1,78 @@
+/**
+ * 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.notification.domain;
+
+
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.useradministration.domain.AppUser;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "notification_mapper")
+public class NotificationMapper extends AbstractPersistableCustom<Long> {
+
+    @ManyToOne
+    @JoinColumn(name = "notification_id")
+    private Notification notification;
+
+    @ManyToOne
+    @JoinColumn(name = "user_id")
+    private AppUser userId;
+
+    @Column(name = "is_read")
+    private boolean isRead;
+
+    @Column(name = "created_at")
+    private String createdAt;
+
+    public NotificationMapper() {}
+
+    public NotificationMapper(Notification notification, AppUser userId, boolean isRead, String createdAt) {
+        this.notification = notification;
+        this.userId = userId;
+        this.isRead = isRead;
+        this.createdAt = createdAt;
+    }
+
+    public Notification getNotification() {
+        return notification;
+    }
+
+    public void setNotification(Notification notification) {
+        this.notification = notification;
+    }
+
+    public AppUser getUserId() {
+        return userId;
+    }
+
+    public void setUserId(AppUser userId) {
+        this.userId = userId;
+    }
+
+    public boolean isRead() {
+        return isRead;
+    }
+
+    public void setRead(boolean read) {
+        isRead = read;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
new file mode 100644
index 0000000..fb88509
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationMapperRepository.java
@@ -0,0 +1,24 @@
+/**
+ * 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.notification.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+
+public interface NotificationMapperRepository extends JpaRepository<NotificationMapper, Long> {}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
new file mode 100644
index 0000000..ed0675d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/domain/NotificationRepository.java
@@ -0,0 +1,24 @@
+/**
+ * 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.notification.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+
+public interface NotificationRepository extends JpaRepository<Notification, Long> {}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
new file mode 100644
index 0000000..bf80437
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventListener.java
@@ -0,0 +1,96 @@
+/**
+ * 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.notification.eventandlistener;
+
+import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.infrastructure.security.service.BasicAuthTenantDetailsService;
+import org.apache.fineract.notification.data.NotificationData;
+import org.apache.fineract.notification.service.NotificationWritePlatformService;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.listener.SessionAwareMessageListener;
+import org.springframework.stereotype.Service;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.ObjectMessage;
+import javax.jms.Session;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+@Service
+public class NotificationEventListener implements SessionAwareMessageListener {
+
+    private final BasicAuthTenantDetailsService basicAuthTenantDetailsService;
+
+    private final NotificationWritePlatformService notificationWritePlatformService;
+
+    private final AppUserRepository appUserRepository;
+
+    @Autowired
+    public NotificationEventListener(BasicAuthTenantDetailsService basicAuthTenantDetailsService,
+                                     NotificationWritePlatformService notificationWritePlatformService,
+                                     AppUserRepository appUserRepository) {
+        this.basicAuthTenantDetailsService = basicAuthTenantDetailsService;
+        this.notificationWritePlatformService = notificationWritePlatformService;
+        this.appUserRepository = appUserRepository;
+    }
+
+    @Override
+    public void onMessage(Message message, Session session) throws JMSException {
+        if (message instanceof ObjectMessage) {
+            NotificationData notificationData = (NotificationData) ((ObjectMessage) message).getObject();
+
+            final FineractPlatformTenant tenant = this.basicAuthTenantDetailsService
+                    .loadTenantById(notificationData.getTenantIdentifier(), false);
+            ThreadLocalContextUtil.setTenant(tenant);
+
+            Long appUserId = notificationData.getActor();
+
+            List<Long> userIds = notificationData.getUserIds();
+
+            if (notificationData.getOfficeId() != null) {
+                List<Long> tempUserIds = new ArrayList<>(userIds);
+                for (Long userId : tempUserIds) {
+                    AppUser appUser = appUserRepository.findOne(userId);
+                    if (!Objects.equals(appUser.getOffice().getId(), notificationData.getOfficeId())) {
+                        userIds.remove(userId);
+                    }
+                }
+            }
+
+            if (userIds.contains(appUserId)) {
+                userIds.remove(appUserId);
+            }
+
+            notificationWritePlatformService.notify(
+                    userIds,
+                    notificationData.getObjectType(),
+                    notificationData.getObjectIdentfier(),
+                    notificationData.getAction(),
+                    notificationData.getActor(),
+                    notificationData.getContent(),
+                    notificationData.isSystemGenerated()
+            );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventService.java b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventService.java
new file mode 100644
index 0000000..a2f32df
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/eventandlistener/NotificationEventService.java
@@ -0,0 +1,50 @@
+/**
+ * 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.notification.eventandlistener;
+
+import org.apache.fineract.notification.data.NotificationData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.stereotype.Service;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+@Service
+public class NotificationEventService {
+
+    private final JmsTemplate jmsTemplate;
+
+    @Autowired
+    public NotificationEventService(JmsTemplate jmsTemplate) {
+        this.jmsTemplate = jmsTemplate;
+    }
+
+    public void broadcastNotification(final Destination destination, final NotificationData notificationData) {
+        this.jmsTemplate.send(destination, new MessageCreator() {
+            @Override
+            public Message createMessage(Session session) throws JMSException {
+                return session.createObjectMessage(notificationData);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainService.java
new file mode 100644
index 0000000..7044aa9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainService.java
@@ -0,0 +1,23 @@
+/**
+ * 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.notification.service;
+
+public interface NotificationDomainService {
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
new file mode 100644
index 0000000..e8becbe
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationDomainServiceImpl.java
@@ -0,0 +1,590 @@
+/**
+ * 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.notification.service;
+
+
+import org.apache.activemq.command.ActiveMQQueue;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.notification.data.NotificationData;
+import org.apache.fineract.notification.eventandlistener.NotificationEventService;
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
+import org.apache.fineract.portfolio.common.service.BusinessEventListner;
+import org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
+import org.apache.fineract.portfolio.loanaccount.domain.Loan;
+import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
+import org.apache.fineract.portfolio.savings.DepositAccountType;
+import org.apache.fineract.portfolio.savings.domain.FixedDepositAccount;
+import org.apache.fineract.portfolio.savings.domain.RecurringDepositAccount;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountTransaction;
+import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.apache.fineract.useradministration.domain.Role;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.jms.Queue;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@Service
+public class NotificationDomainServiceImpl implements NotificationDomainService {
+
+    private final BusinessEventNotifierService businessEventNotifierService;
+    private final NotificationEventService notificationEventService;
+    private final AppUserRepository appUserRepository;
+    private final PlatformSecurityContext context;
+
+
+    @Autowired
+    public NotificationDomainServiceImpl(final BusinessEventNotifierService businessEventNotifierService,
+                                         final NotificationEventService notificationEventService,
+                                         final AppUserRepository appUserRepository,
+                                         final PlatformSecurityContext context) {
+        this.businessEventNotifierService = businessEventNotifierService;
+        this.notificationEventService = notificationEventService;
+        this.appUserRepository = appUserRepository;
+        this.context = context;
+    }
+
+    @PostConstruct
+    public void addListeners() {
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.CLIENTS_CREATE,
+                new ClientCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_APPROVE,
+                new SavingsAccountApprovedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.CENTERS_CREATE,
+                new CenterCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.GROUPS_CREATE,
+                new GroupCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_DEPOSIT,
+                new SavingsAccountDepositListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_PRODUCT_DIVIDENDS_CREATE,
+                new ShareProductDividendCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.FIXED_DEPOSIT_ACCOUNT_CREATE,
+                new FixedDepositAccountCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.RECURRING_DEPOSIT_ACCOUNT_CREATE,
+                new RecurringDepositAccountCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_POST_INTEREST,
+                new SavingsPostInterestListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CREATE,
+                new LoanCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_APPROVED,
+                new LoanApprovedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CLOSE,
+                new LoanClosedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_CLOSE_AS_RESCHEDULE,
+                new LoanCloseAsRescheduledListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_MAKE_REPAYMENT,
+                new LoanMakeRepaymentListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.LOAN_PRODUCT_CREATE,
+                new LoanProductCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_CREATE,
+                new SavingsAccountCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SAVINGS_CLOSE,
+                new SavingsAccountClosedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_ACCOUNT_CREATE,
+                new ShareAccountCreatedListener());
+        businessEventNotifierService.addBusinessEventPostListners(BUSINESS_EVENTS.SHARE_ACCOUNT_APPROVE,
+                new ShareAccountApprovedListener());
+    }
+
+    private abstract class NotificationBusinessEventAdapter implements BusinessEventListner {
+
+        @Override
+        public void businessEventToBeExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+            //Nothing to do
+        }
+    }
+
+    private class ClientCreatedListener extends  NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+            Client client;
+            Object entity = businessEventEntity.get(BusinessEventNotificationConstants.BUSINESS_ENTITY.CLIENT);
+            if (entity != null) {
+                client = (Client) entity;
+                buildNotification(
+                        "ACTIVATE_CLIENT",
+                        "client",
+                        client.getId(),
+                        "New client created",
+                        "created",
+                        context.authenticatedUser().getId(),
+                        client.getOffice().getId()
+                );
+            }
+        }
+    }
+
+    private class CenterCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+            CommandProcessingResult commandProcessingResult;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.GROUP);
+            if (entity != null) {
+                commandProcessingResult = (CommandProcessingResult) entity;
+                buildNotification(
+                        "ACTIVATE_CENTER",
+                        "center",
+                        commandProcessingResult.getGroupId(),
+                        "New center created",
+                        "created",
+                        context.authenticatedUser().getId(),
+                        commandProcessingResult.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class GroupCreatedListener extends  NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> businessEventEntity) {
+            CommandProcessingResult commandProcessingResult;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.GROUP);
+            if (entity != null) {
+                commandProcessingResult = (CommandProcessingResult) entity;
+                buildNotification(
+                        "ACTIVATE_GROUP",
+                        "group",
+                        commandProcessingResult.getGroupId(),
+                        "New group created",
+                        "created",
+                        context.authenticatedUser().getId(),
+                        commandProcessingResult.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class SavingsAccountDepositListener extends  NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            SavingsAccountTransaction savingsAccountTransaction;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVINGS_TRANSACTION);
+            if (entity != null) {
+                savingsAccountTransaction = (SavingsAccountTransaction) entity;
+                buildNotification(
+                        "READ_SAVINGSACCOUNT",
+                        "savingsAccount",
+                        savingsAccountTransaction.getSavingsAccount().getId(),
+                        "Deposit made",
+                        "depositMade",
+                        context.authenticatedUser().getId(),
+                        savingsAccountTransaction.getSavingsAccount().officeId()
+                );
+            }
+        }
+    }
+
+    private class ShareProductDividendCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            Long shareProductId;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_PRODUCT);
+            if (entity != null) {
+                shareProductId = (Long) entity;
+                buildNotification(
+                        "READ_DIVIDEND_SHAREPRODUCT",
+                        "shareProduct",
+                        shareProductId,
+                        "Dividend posted to account",
+                        "dividendPosted",
+                        context.authenticatedUser().getId(),
+                        context.authenticatedUser().getOffice().getId()
+                );
+            }
+        }
+    }
+
+    private class FixedDepositAccountCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            FixedDepositAccount fixedDepositAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.DEPOSIT_ACCOUNT);
+            if (entity != null) {
+                fixedDepositAccount = (FixedDepositAccount) entity;
+                buildNotification(
+                        "APPROVE_FIXEDDEPOSITACCOUNT",
+                        "fixedDeposit",
+                        fixedDepositAccount.getId(),
+                        "New fixed deposit account created",
+                        "created",
+                        context.authenticatedUser().getId(),
+                        fixedDepositAccount.officeId()
+                );
+            }
+        }
+    }
+
+    private class RecurringDepositAccountCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            RecurringDepositAccount recurringDepositAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.DEPOSIT_ACCOUNT);
+            if (entity != null) {
+                recurringDepositAccount = (RecurringDepositAccount) entity;
+                buildNotification(
+                        "APPROVE_RECURRINGDEPOSITACCOUNT",
+                        "recurringDepositAccount",
+                        recurringDepositAccount.getId(),
+                        "New recurring deposit account created",
+                        "created",
+                        context.authenticatedUser().getId(),
+                        recurringDepositAccount.officeId()
+                );
+            }
+        }
+    }
+
+
+    private class SavingsAccountApprovedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            SavingsAccount  savingsAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+            if (entity != null) {
+                savingsAccount = (SavingsAccount) entity;
+                if (savingsAccount.depositAccountType().equals(DepositAccountType.FIXED_DEPOSIT)) {
+
+                    buildNotification(
+                        "ACTIVATE_FIXEDDEPOSITACCOUNT",
+                        "fixedDeposit",
+                        savingsAccount.getId(),
+                        "Fixed deposit account approved",
+                        "approved",
+                        context.authenticatedUser().getId(),
+                        savingsAccount.officeId()
+                    );
+
+                } else if (savingsAccount.depositAccountType().equals(DepositAccountType.RECURRING_DEPOSIT)) {
+
+                    buildNotification(
+                        "ACTIVATE_RECURRINGDEPOSITACCOUNT",
+                        "recurringDepositAccount",
+                        savingsAccount.getId(),
+                        "Recurring deposit account approved",
+                        "approved",
+                        context.authenticatedUser().getId(),
+                        savingsAccount.officeId()
+                    );
+
+                } else if (savingsAccount.depositAccountType().equals(DepositAccountType.SAVINGS_DEPOSIT)) {
+
+                    buildNotification(
+                        "ACTIVATE_SAVINGSACCOUNT",
+                        "savingsAccount",
+                        savingsAccount.getId(),
+                        "Savings account approved",
+                        "approved",
+                        context.authenticatedUser().getId(),
+                        savingsAccount.officeId()
+                    );
+                }
+            }
+        }
+    }
+
+    private class SavingsPostInterestListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            SavingsAccount savingsAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+            if (entity != null) {
+                savingsAccount = (SavingsAccount) entity;
+                buildNotification(
+                    "READ_SAVINGSACCOUNT",
+                    "savingsAccount",
+                    savingsAccount.getId(),
+                    "Interest posted to account",
+                    "interestPosted",
+                    context.authenticatedUser().getId(),
+                    savingsAccount.officeId()
+                );
+            }
+        }
+    }
+
+    private class LoanCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            Loan loan;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+            if (entity != null) {
+                loan = (Loan) entity;
+                buildNotification(
+                    "APPROVE_LOAN",
+                    "loan",
+                    loan.getId(),
+                    "New loan created",
+                    "created",
+                    context.authenticatedUser().getId(),
+                    loan.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class LoanApprovedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            Loan loan;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+            if (entity != null) {
+                loan = (Loan) entity;
+                buildNotification(
+                    "DISBURSE_LOAN",
+                    "loan",
+                    loan.getId(),
+                    "New loan approved",
+                    "approved",
+                    context.authenticatedUser().getId(),
+                    loan.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class LoanClosedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            Loan loan;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+            if (entity != null) {
+                loan = (Loan) entity;
+                buildNotification(
+                    "READ_LOAN",
+                    "loan",
+                    loan.getId(),
+                    "Loan closed",
+                    "loanClosed",
+                    context.authenticatedUser().getId(),
+                    loan.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class LoanCloseAsRescheduledListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            Loan loan;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+            if (entity != null) {
+                loan = (Loan) entity;
+                buildNotification(
+                    "READ_Rescheduled Loans",
+                    "loan",
+                    loan.getId(),
+                    "Loan has been rescheduled",
+                    "loanRescheduled",
+                    context.authenticatedUser().getId(),
+                    loan.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class LoanMakeRepaymentListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            Loan loan;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN);
+            if (entity != null) {
+                loan = (Loan) entity;
+                buildNotification(
+                    "READ_LOAN",
+                    "loan",
+                    loan.getId(),
+                    "Repayment made",
+                    "repaymentMade",
+                    context.authenticatedUser().getId(),
+                    loan.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class LoanProductCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+
+            LoanProduct loanProduct;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.LOAN_PRODUCT);
+            if (entity != null) {
+                loanProduct = (LoanProduct) entity;
+                buildNotification(
+                    "READ_LOANPRODUCT",
+                    "loanProduct",
+                    loanProduct.getId(),
+                    "New loan product created",
+                    "created",
+                    context.authenticatedUser().getId(),
+                    context.authenticatedUser().getOffice().getId()
+                );
+            }
+        }
+    }
+
+    private class SavingsAccountCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            SavingsAccount  savingsAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+            if (entity != null) {
+                savingsAccount = (SavingsAccount) entity;
+                buildNotification(
+                    "APPROVE_SAVINGSACCOUNT",
+                    "savingsAccount",
+                    savingsAccount.getId(),
+                    "New savings account created",
+                    "created",
+                    context.authenticatedUser().getId(),
+                    savingsAccount.officeId()
+                );
+            }
+        }
+    }
+
+    private class SavingsAccountClosedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            SavingsAccount  savingsAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SAVING);
+            if (entity != null) {
+                savingsAccount = (SavingsAccount) entity;
+                buildNotification(
+                    "READ_SAVINGSACCOUNT",
+                    "savingsAccount",
+                    savingsAccount.getId(),
+                    "Savings has gone into dormant",
+                    "closed",
+                    context.authenticatedUser().getId(),
+                    savingsAccount.officeId()
+                );
+            }
+        }
+    }
+
+    private class ShareAccountCreatedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            ShareAccount shareAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_ACCOUNT);
+            if (entity != null) {
+                shareAccount = (ShareAccount) entity;
+                buildNotification(
+                    "APPROVE_SHAREACCOUNT",
+                    "shareAccount",
+                    shareAccount.getId(),
+                    "New share account created",
+                    "created",
+                    context.authenticatedUser().getId(),
+                    shareAccount.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private class ShareAccountApprovedListener extends NotificationBusinessEventAdapter {
+
+        @Override
+        public void businessEventWasExecuted(Map<BUSINESS_ENTITY, Object> businessEventEntity) {
+            ShareAccount shareAccount;
+            Object entity = businessEventEntity.get(BUSINESS_ENTITY.SHARE_ACCOUNT);
+            if (entity != null) {
+                shareAccount = (ShareAccount) entity;
+                buildNotification(
+                    "ACTIVATE_SHAREACCOUNT",
+                    "shareAccount",
+                    shareAccount.getId(),
+                    "Share account approved",
+                    "approved",
+                    context.authenticatedUser().getId(),
+                    shareAccount.getOfficeId()
+                );
+            }
+        }
+    }
+
+    private void buildNotification(String permission, String objectType,
+                                   Long objectIdentifier, String notificationContent, String eventType,
+                                   Long appUserId, Long officeId) {
+
+        String tenantIdentifier = ThreadLocalContextUtil.getTenant().getTenantIdentifier();
+        Queue queue = new ActiveMQQueue("NotificationQueue");
+        List<Long> userIds = retrieveUsersWithSpecificPermission(permission);
+        NotificationData notificationData = new NotificationData(
+                objectType,
+                objectIdentifier,
+                eventType,
+                appUserId,
+                notificationContent,
+                false,
+                tenantIdentifier,
+                officeId,
+                userIds
+        );
+        notificationEventService.broadcastNotification(queue, notificationData);
+
+    }
+
+    private List<Long> retrieveUsersWithSpecificPermission(String permission) {
+        List<AppUser> appUsers = appUserRepository.findAll();
+        List<Long> userIds = new ArrayList<>();
+        for (AppUser appUser : appUsers) {
+            Set<Role> roles = appUser.getRoles();
+            for (Role role : roles) {
+                if (role.hasPermissionTo(permission)) {
+                    if (!(userIds.contains(appUser.getId()))) {
+                        userIds.add(appUser.getId());
+                    }
+                }
+            }
+        }
+        return userIds;
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapper.java
new file mode 100644
index 0000000..8004382
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapper.java
@@ -0,0 +1,35 @@
+/**
+ * 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.notification.service;
+
+import org.apache.fineract.notification.domain.Notification;
+
+import java.util.List;
+
+
+public interface NotificationGeneratorReadRepositoryWrapper {
+
+
+    Notification findById(Long id);
+
+    List<Notification> fetchAllNotifications();
+
+    void delete(Long id);
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapperImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapperImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapperImpl.java
new file mode 100644
index 0000000..2bba025
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorReadRepositoryWrapperImpl.java
@@ -0,0 +1,53 @@
+/**
+ * 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.notification.service;
+
+import org.apache.fineract.notification.domain.Notification;
+import org.apache.fineract.notification.domain.NotificationRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class NotificationGeneratorReadRepositoryWrapperImpl implements NotificationGeneratorReadRepositoryWrapper {
+
+    private final NotificationRepository notificationRepository;
+
+    @Autowired
+    public NotificationGeneratorReadRepositoryWrapperImpl(NotificationRepository notificationRepository) {
+        this.notificationRepository = notificationRepository;
+    }
+
+    @Override
+    public Notification findById(Long id) {
+        return this.notificationRepository.findOne(id);
+    }
+
+    @Override
+    public List<Notification> fetchAllNotifications() {
+        return this.notificationRepository.findAll();
+    }
+
+    @Override
+    public void delete(Long id) {
+       this.notificationRepository.delete(id);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformService.java
new file mode 100644
index 0000000..1941955
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformService.java
@@ -0,0 +1,27 @@
+/**
+ * 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.notification.service;
+
+import org.apache.fineract.notification.domain.Notification;
+
+public interface NotificationGeneratorWritePlatformService  {
+
+    Long create(Notification notification);
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java
new file mode 100644
index 0000000..c78cbe7
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationGeneratorWritePlatformServiceImpl.java
@@ -0,0 +1,41 @@
+/**
+ * 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.notification.service;
+
+import org.apache.fineract.notification.domain.Notification;
+import org.apache.fineract.notification.domain.NotificationRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class NotificationGeneratorWritePlatformServiceImpl implements NotificationGeneratorWritePlatformService {
+
+    private final NotificationRepository notificationRepository;
+
+    @Autowired
+    public NotificationGeneratorWritePlatformServiceImpl(NotificationRepository notificationRepository) {
+        this.notificationRepository = notificationRepository;
+    }
+
+    @Override
+    public Long create(Notification notification) {
+        this.notificationRepository.save(notification);
+        return notification.getId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapper.java
new file mode 100644
index 0000000..157f2ff
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapper.java
@@ -0,0 +1,34 @@
+/**
+ * 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.notification.service;
+
+import org.apache.fineract.notification.domain.NotificationMapper;
+
+import java.util.List;
+
+public interface NotificationMapperReadRepositoryWrapper {
+
+
+    NotificationMapper findById(Long id);
+
+    List<NotificationMapper> fetchAllNotifications();
+
+    void delete(Long id);
+
+}