http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapperImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapperImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapperImpl.java
new file mode 100644
index 0000000..88dc2ac
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperReadRepositoryWrapperImpl.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.NotificationMapper;
+import org.apache.fineract.notification.domain.NotificationMapperRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class NotificationMapperReadRepositoryWrapperImpl implements 
NotificationMapperReadRepositoryWrapper {
+
+    private final NotificationMapperRepository notificationMapperRepository;
+
+    @Autowired
+    public 
NotificationMapperReadRepositoryWrapperImpl(NotificationMapperRepository 
notificationMapperRepository) {
+        this.notificationMapperRepository = notificationMapperRepository;
+    }
+
+    @Override
+    public NotificationMapper findById(Long id) {
+        return this.notificationMapperRepository.findOne(id);
+    }
+
+    @Override
+    public List<NotificationMapper> fetchAllNotifications() {
+        return this.notificationMapperRepository.findAll();
+    }
+
+    @Override
+    public void delete(Long id) {
+        this.notificationMapperRepository.delete(id);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.java
new file mode 100644
index 0000000..72c2ded
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationMapperWritePlatformService.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.NotificationMapper;
+
+
+public interface NotificationMapperWritePlatformService {
+
+    Long create(NotificationMapper notificationMapper);
+}

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

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformService.java
new file mode 100644
index 0000000..fd631f7
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformService.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.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.notification.data.NotificationData;
+
+public interface NotificationReadPlatformService {
+
+    boolean hasUnreadNotifications(Long appUserId);
+
+    Page<NotificationData> getAllUnreadNotifications(SearchParameters 
searchParameters);
+
+    Page<NotificationData> getAllNotifications(SearchParameters 
searchParameters);
+
+    void updateNotificationReadStatus();
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
new file mode 100644
index 0000000..c701be2
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationReadPlatformServiceImpl.java
@@ -0,0 +1,219 @@
+/**
+ * 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.infrastructure.core.service.*;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.notification.cache.CacheNotificationResponseHeader;
+import org.apache.fineract.notification.data.NotificationData;
+import org.apache.fineract.notification.data.NotificationMapperData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+
+@Service
+public class NotificationReadPlatformServiceImpl implements 
NotificationReadPlatformService {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final PlatformSecurityContext context;
+    private final PaginationHelper<NotificationData> paginationHelper = new 
PaginationHelper<>();
+    private final NotificationDataRow notificationDataRow = new 
NotificationDataRow();
+    private final NotificationMapperRow notificationMapperRow = new 
NotificationMapperRow();
+    private HashMap<Long, HashMap<Long, CacheNotificationResponseHeader>>
+            tenantNotificationResponseHeaderCache = new HashMap<>();
+
+    @Autowired
+    public NotificationReadPlatformServiceImpl(final RoutingDataSource 
dataSource, final PlatformSecurityContext context) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+        this.context = context;
+    }
+
+    @Override
+    public boolean hasUnreadNotifications(Long appUserId) {
+        Long tenantId = ThreadLocalContextUtil.getTenant().getId();
+        Long now = System.currentTimeMillis()/1000L;
+        if (this.tenantNotificationResponseHeaderCache.containsKey(tenantId)) {
+            HashMap<Long, CacheNotificationResponseHeader> 
notificationResponseHeaderCache =
+                    this.tenantNotificationResponseHeaderCache.get(tenantId);
+            if (notificationResponseHeaderCache.containsKey(appUserId)) {
+                Long lastFetch = 
notificationResponseHeaderCache.get(appUserId).getLastFetch();
+                if ((now - lastFetch) > 1) {
+                    return this.createUpdateCacheValue(appUserId, now, 
notificationResponseHeaderCache);
+                } else {
+                    return 
notificationResponseHeaderCache.get(appUserId).hasNotifications();
+                }
+            } else {
+                return this.createUpdateCacheValue(appUserId, now, 
notificationResponseHeaderCache);
+            }
+        } else {
+            return 
this.initializeTenantNotificationResponseHeaderCache(tenantId, now, appUserId);
+
+        }
+    }
+
+    private boolean initializeTenantNotificationResponseHeaderCache(Long 
tenantId, Long now, Long appUserId) {
+        HashMap<Long, CacheNotificationResponseHeader> 
notificationResponseHeaderCache = new HashMap<>();
+        this.tenantNotificationResponseHeaderCache.put(tenantId, 
notificationResponseHeaderCache);
+        return this.createUpdateCacheValue(appUserId, now, 
notificationResponseHeaderCache);
+    }
+
+    private boolean createUpdateCacheValue(Long appUserId, Long now, 
HashMap<Long,
+            CacheNotificationResponseHeader> notificationResponseHeaderCache) {
+        boolean hasNotifications;
+        Long tenantId = ThreadLocalContextUtil.getTenant().getId();
+        CacheNotificationResponseHeader cacheNotificationResponseHeader;
+        hasNotifications = checkForUnreadNotifications(appUserId);
+        cacheNotificationResponseHeader = new 
CacheNotificationResponseHeader(hasNotifications, now);
+        notificationResponseHeaderCache.put(appUserId, 
cacheNotificationResponseHeader);
+        this.tenantNotificationResponseHeaderCache.put(tenantId, 
notificationResponseHeaderCache);
+        return hasNotifications;
+    }
+
+    private boolean checkForUnreadNotifications(Long appUserId) {
+        String sql = "SELECT id, notification_id as notificationId, user_id as 
userId, is_read as isRead, created_at " +
+                "as createdAt FROM notification_mapper WHERE user_id = ? AND 
is_read = false";
+        List<NotificationMapperData > notificationMappers = 
this.jdbcTemplate.query(
+                sql,
+                notificationMapperRow,
+                appUserId);
+        return notificationMappers.size() > 0;
+    }
+
+    @Override
+    public void updateNotificationReadStatus() {
+        final Long appUserId = context.authenticatedUser().getId();
+        String sql = "UPDATE notification_mapper SET is_read = true WHERE 
is_read = false and user_id = ?";
+        this.jdbcTemplate.update(sql, appUserId);
+    }
+
+    @Override
+    public Page<NotificationData> getAllUnreadNotifications(final 
SearchParameters searchParameters) {
+        final Long appUserId = context.authenticatedUser().getId();
+        String sql = "SELECT SQL_CALC_FOUND_ROWS ng.id as id, nm.user_id as 
userId, ng.object_type as objectType, " +
+                "ng.object_identifier as objectId, ng.actor as actor, 
ng.action action, ng.notification_content " +
+                "as content, ng.is_system_generated as isSystemGenerated, 
nm.created_at as createdAt " +
+                "FROM notification_mapper nm INNER JOIN notification_generator 
ng ON nm.notification_id = ng.id " +
+                "WHERE nm.user_id = ? AND nm.is_read = false order by 
nm.created_at desc";
+
+        return getNotificationDataPage(searchParameters, appUserId, sql);
+    }
+
+
+    @Override
+    public Page<NotificationData> getAllNotifications(SearchParameters 
searchParameters) {
+        final Long appUserId = context.authenticatedUser().getId();
+        String sql = "SELECT SQL_CALC_FOUND_ROWS ng.id as id, nm.user_id as 
userId, ng.object_type as objectType, " +
+                "ng.object_identifier as objectId, ng.actor as actor, 
ng.action action, ng.notification_content " +
+                "as content, ng.is_system_generated as isSystemGenerated, 
nm.created_at as createdAt " +
+                "FROM notification_mapper nm INNER JOIN notification_generator 
ng ON nm.notification_id = ng.id " +
+                "WHERE nm.user_id = ? order by nm.created_at desc";
+
+        return getNotificationDataPage(searchParameters, appUserId, sql);
+    }
+
+    private Page<NotificationData> getNotificationDataPage(SearchParameters 
searchParameters, Long appUserId, String sql) {
+        final StringBuilder sqlBuilder = new StringBuilder(200);
+        sqlBuilder.append(sql);
+
+        if (searchParameters.isOrderByRequested()) {
+            sqlBuilder.append(" order by 
").append(searchParameters.getOrderBy());
+
+            if (searchParameters.isSortOrderProvided()) {
+                sqlBuilder.append(' ').append(searchParameters.getSortOrder());
+            }
+        }
+
+        if (searchParameters.isLimited()) {
+            sqlBuilder.append(" limit ").append(searchParameters.getLimit());
+            if (searchParameters.isOffset()) {
+                sqlBuilder.append(" offset 
").append(searchParameters.getOffset());
+            }
+        }
+
+        final String sqlCountRows = "SELECT FOUND_ROWS()";
+        Object[] params = new Object[]{appUserId};
+        return this.paginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows, sqlBuilder.toString(),
+                params, this.notificationDataRow);
+    }
+
+    private static final class NotificationMapperRow implements 
RowMapper<NotificationMapperData> {
+
+        @Override
+        public NotificationMapperData mapRow(ResultSet rs, int rowNum) throws 
SQLException {
+            NotificationMapperData notificationMapperData = new 
NotificationMapperData();
+
+            final Long id = rs.getLong("id");
+            notificationMapperData.setId(id);
+
+            final Long notificationId = rs.getLong("notificationId");
+            notificationMapperData.setNotificationId(notificationId);
+
+            final Long userId = rs.getLong("userId");
+            notificationMapperData.setUserId(userId);
+
+            final boolean isRead = rs.getBoolean("isRead");
+            notificationMapperData.setRead(isRead);
+
+            final String createdAt = rs.getString("createdAt");
+            notificationMapperData.setCreatedAt(createdAt);
+
+            return notificationMapperData;
+        }
+    }
+
+    private static final class NotificationDataRow implements 
RowMapper<NotificationData> {
+
+        @Override
+        public NotificationData mapRow(ResultSet rs, int rowNum) throws 
SQLException {
+            NotificationData notificationData = new NotificationData();
+
+            final Long id = rs.getLong("id");
+            notificationData.setId(id);
+
+            final String objectType = rs.getString("objectType");
+            notificationData.setObjectType(objectType);
+
+            final Long objectId = rs.getLong("objectId");
+            notificationData.entifier(objectId);
+
+            final Long actorId = rs.getLong("actor");
+            notificationData.setActor(actorId);
+
+            final String action = rs.getString("action");
+            notificationData.setAction(action);
+
+            final String content = rs.getString("content");
+            notificationData.setContent(content);
+
+            final boolean isSystemGenerated = 
rs.getBoolean("isSystemGenerated");
+            notificationData.setSystemGenerated(isSystemGenerated);
+
+            final String createdAt = rs.getString("createdAt");
+            notificationData.setCreatedAt(createdAt);
+
+            return notificationData;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
new file mode 100644
index 0000000..703cf8e
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformService.java
@@ -0,0 +1,29 @@
+/**
+ * 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 java.util.List;
+
+public interface NotificationWritePlatformService {
+    Long notify(Long userId, String objectType, Long objectId, String action,
+                Long actorId, String notificationContent, boolean 
isSystemGenerated);
+
+    Long notify(List<Long> userIds, String objectType, Long objectId, String 
action,
+                Long actorId, String notificationContent, boolean 
isSystemGenerated);
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
new file mode 100644
index 0000000..acab2a3
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/notification/service/NotificationWritePlatformServiceImpl.java
@@ -0,0 +1,129 @@
+/**
+ * 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.NotificationMapper;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Service
+public class NotificationWritePlatformServiceImpl implements 
NotificationWritePlatformService {
+
+    private final NotificationGeneratorWritePlatformService 
notificationGeneratorWritePlatformService;
+
+    private final NotificationGeneratorReadRepositoryWrapper 
notificationGeneratorReadRepositoryWrapper;
+
+    private final AppUserRepository appUserRepository;
+
+    private final NotificationMapperWritePlatformService 
notificationMapperWritePlatformService;
+
+    @Autowired
+    public NotificationWritePlatformServiceImpl(
+            final NotificationGeneratorWritePlatformService 
notificationGeneratorWritePlatformService,
+            final NotificationGeneratorReadRepositoryWrapper 
notificationGeneratorReadRepositoryWrapper,
+            final AppUserRepository appUserRepository,
+            final NotificationMapperWritePlatformService 
notificationMapperWritePlatformService) {
+        this.notificationGeneratorWritePlatformService = 
notificationGeneratorWritePlatformService;
+        this.notificationGeneratorReadRepositoryWrapper = 
notificationGeneratorReadRepositoryWrapper;
+        this.appUserRepository = appUserRepository;
+        this.notificationMapperWritePlatformService = 
notificationMapperWritePlatformService;
+    }
+
+
+    @Override
+    public Long notify(Long userId, String objectType, Long objectIdentifier, 
String action,
+                       Long actorId, String notificationContent, boolean 
isSystemGenerated) {
+
+        Long generatedNotificationId = 
insertIntoNotificationGenerator(objectType, objectIdentifier, action,
+                actorId, notificationContent, isSystemGenerated);
+        insertIntoNotificationMapper(userId, generatedNotificationId);
+        return generatedNotificationId;
+    }
+
+    private Long insertIntoNotificationMapper(Long userId, Long 
generatedNotificationId) {
+        AppUser appUser = this.appUserRepository.findOne(userId);
+        NotificationMapper notificationMapper = new NotificationMapper(
+                
this.notificationGeneratorReadRepositoryWrapper.findById(generatedNotificationId),
+                appUser,
+                false,
+                getCurrentDateTime()
+        );
+
+        this.notificationMapperWritePlatformService.create(notificationMapper);
+        return notificationMapper.getId();
+    }
+
+    private Long insertIntoNotificationGenerator(String objectType, Long 
objectIdentifier, String action,
+                                                 Long actorId, String 
notificationContent,
+                                                 boolean isSystemGenerated) {
+
+        Notification notification = new Notification(
+                objectType,
+                objectIdentifier,
+                action,
+                actorId,
+                isSystemGenerated,
+                notificationContent,
+                getCurrentDateTime()
+        );
+
+        return 
this.notificationGeneratorWritePlatformService.create(notification);
+    }
+
+    @Override
+    public Long notify(List<Long> userIds, String objectType, Long objectId, 
String action,
+                       Long actorId, String notificationContent, boolean 
isSystemGenerated) {
+
+        Long generatedNotificationId = 
insertIntoNotificationGenerator(objectType, objectId, action,
+                actorId, notificationContent, isSystemGenerated);
+
+        insertIntoNotificationMapper(userIds, generatedNotificationId);
+        return generatedNotificationId;
+    }
+
+    private List<Long> insertIntoNotificationMapper(List<Long> userIds, Long 
generatedNotificationId) {
+        List<Long> mappedIds = new ArrayList<>();
+        for (Long userId : userIds) {
+            AppUser appUser = this.appUserRepository.findOne(userId);
+            NotificationMapper notificationMapper = new NotificationMapper(
+                    
this.notificationGeneratorReadRepositoryWrapper.findById(generatedNotificationId),
+                    appUser,
+                    false,
+                    getCurrentDateTime()
+            );
+            
this.notificationMapperWritePlatformService.create(notificationMapper);
+            mappedIds.add(notificationMapper.getId());
+        }
+        return mappedIds;
+    }
+
+    private String getCurrentDateTime() {
+        Date date = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss");
+        return formatter.format(date);
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
index a649e51..72d8c49 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java
@@ -342,6 +342,9 @@ public class ClientWritePlatformServiceJpaRepositoryImpl 
implements ClientWriteP
                         
command.arrayOfParameterNamed(ClientApiConstants.datatables));
             }
 
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.CLIENT, newClient));
+
             
this.entityDatatableChecksWritePlatformService.runTheCheck(newClient.getId(), 
EntityTables.CLIENT.getName(),
                     StatusEnum.CREATE.getCode().longValue(), 
EntityTables.CLIENT.getForeignKeyColumnNameOnDatatable());
             return new CommandProcessingResultBuilder() //

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
index 0556f9c..4a11d02 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/common/BusinessEventNotificationConstants.java
@@ -32,10 +32,13 @@ public class BusinessEventNotificationConstants {
                 "loan_update_charge"), LOAN_WAIVE_CHARGE("loan_waive_charge"), 
LOAN_DELETE_CHARGE("loan_delete_charge"), LOAN_CHARGE_PAYMENT(
                 "loan_charge_payment"), 
LOAN_INITIATE_TRANSFER("loan_initiate_transfer"), 
LOAN_ACCEPT_TRANSFER("loan_accept_transfer"), LOAN_WITHDRAW_TRANSFER(
                 "loan_withdraw_transfer"), 
LOAN_REJECT_TRANSFER("loan_reject_transfer"), 
LOAN_REASSIGN_OFFICER("loan_reassign_officer"), LOAN_REMOVE_OFFICER(
-                "loan_remove_officer"), 
LOAN_APPLY_OVERDUE_CHARGE("loan_apply_overdue_charge"), 
LOAN_INTEREST_RECALCULATION(
-                "loan_interest_recalculation"), LOAN_REFUND("loan_refund"), 
LOAN_FORECLOSURE("loan_foreclosure"), SAVINGS_ACTIVATE(
-                "savings_activated"), SAVINGS_REJECT("savings_reject"), 
SAVINGS_DEPOSIT("savings_deposit"), SAVINGS_WITHDRAWAL(
-                "savings_withdrawal"), CLIENTS_ACTIVATE("clients_activate"), 
CLIENTS_REJECT("clients_reject");
+                "loan_remove_officer"), 
LOAN_APPLY_OVERDUE_CHARGE("loan_apply_overdue_charge"), 
LOAN_INTEREST_RECALCULATION("loan_interest_recalculation"),
+                LOAN_REFUND("loan_refund"), 
LOAN_FORECLOSURE("loan_foreclosure"), LOAN_CREATE("loan_create"), 
LOAN_PRODUCT_CREATE("loan_product_create"), 
SAVINGS_ACTIVATE("savings_activated"),
+                SAVINGS_REJECT("savings_reject"), 
SAVINGS_POST_INTEREST("savings_post_interest"), 
SAVINGS_DEPOSIT("savings_deposit"), SAVINGS_CLOSE("savings_close"),
+                SAVINGS_WITHDRAWAL("savings_withdrawal"), 
SAVINGS_APPROVE("savings_approve"), SAVINGS_CREATE("savings_create"), 
CLIENTS_ACTIVATE("clients_activate"), 
SHARE_ACCOUNT_CREATE("share_account_create"),
+                CLIENTS_REJECT("clients_reject"), 
CLIENTS_CREATE("clients_create"),CENTERS_CREATE("centers_create"), 
GROUPS_CREATE("groups_create"),
+                
SHARE_PRODUCT_DIVIDENDS_CREATE("share_product_dividends_create"),FIXED_DEPOSIT_ACCOUNT_CREATE("fixed_deposit_account_create"),
+                SHARE_ACCOUNT_APPROVE("share_account_approve"), 
RECURRING_DEPOSIT_ACCOUNT_CREATE("recurring_deposit_account_create");
 
         private final String value;
 
@@ -61,7 +64,8 @@ public class BusinessEventNotificationConstants {
 
     public static enum BUSINESS_ENTITY {
         LOAN("loan"), LOAN_TRANSACTION("loan_transaction"), 
LOAN_CHARGE("loan_charge"), LOAN_ADJUSTED_TRANSACTION(
-                "loan_adjusted_transaction"), SAVING("saving"), 
CLIENT("client"), SAVINGS_TRANSACTION("Savings Transaction");
+        "loan_adjusted_transaction"), SAVING("saving"), CLIENT("client"), 
SAVINGS_TRANSACTION("Savings Transaction"), GROUP("group"),
+        SHARE_ACCOUNT("share_account"), SHARE_PRODUCT("share_product"), 
DEPOSIT_ACCOUNT("deposit_account"), LOAN_PRODUCT("loan_product");
 
         private final String value;
 

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
index a3837c0..2616c27 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/group/service/GroupingTypesWritePlatformServiceJpaRepositoryImpl.java
@@ -52,6 +52,8 @@ import 
org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
 import org.apache.fineract.portfolio.client.domain.Client;
 import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
 import org.apache.fineract.portfolio.client.service.LoanStatusMapper;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
+import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.group.api.GroupingTypesApiConstants;
 import org.apache.fineract.portfolio.group.domain.*;
 import org.apache.fineract.portfolio.group.exception.*;
@@ -72,6 +74,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
 
 @Service
 public class GroupingTypesWritePlatformServiceJpaRepositoryImpl implements 
GroupingTypesWritePlatformService {
@@ -95,6 +99,7 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
     private final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository;
     private final AccountNumberGenerator accountNumberGenerator;
     private final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService;
+    private final BusinessEventNotifierService businessEventNotifierService;
 
     @Autowired
     public GroupingTypesWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
@@ -106,7 +111,8 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
             final CalendarInstanceRepository calendarInstanceRepository, final 
ConfigurationDomainService configurationDomainService,
             final LoanRepositoryWrapper loanRepositoryWrapper, 
             final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository, final AccountNumberGenerator 
accountNumberGenerator,
-            final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService) {
+            final EntityDatatableChecksWritePlatformService 
entityDatatableChecksWritePlatformService,
+            final BusinessEventNotifierService businessEventNotifierService) {
         this.context = context;
         this.groupRepository = groupRepository;
         this.clientRepositoryWrapper = clientRepositoryWrapper;
@@ -124,6 +130,7 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
         this.accountNumberFormatRepository = accountNumberFormatRepository;
         this.accountNumberGenerator = accountNumberGenerator;
         this.entityDatatableChecksWritePlatformService = 
entityDatatableChecksWritePlatformService;
+        this.businessEventNotifierService = businessEventNotifierService;
     }
 
     private CommandProcessingResult createGroupingType(final JsonCommand 
command, final GroupTypes groupingType, final Long centerId) {
@@ -263,7 +270,13 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
         this.fromApiJsonDeserializer.validateForCreateCenter(command);
 
         final Long centerId = null;
-        return createGroupingType(command, GroupTypes.CENTER, centerId);
+
+        CommandProcessingResult commandProcessingResult = 
createGroupingType(command, GroupTypes.CENTER, centerId);
+
+        
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CENTERS_CREATE,
+                constructEntityMap(BUSINESS_ENTITY.GROUP, 
commandProcessingResult));
+
+        return commandProcessingResult;
     }
 
     @Transactional
@@ -276,7 +289,12 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
             this.fromApiJsonDeserializer.validateForCreateGroup(command);
         }
 
-        return createGroupingType(command, GroupTypes.GROUP, centerId);
+        CommandProcessingResult commandProcessingResult = 
createGroupingType(command, GroupTypes.GROUP, centerId);
+
+        
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BusinessEventNotificationConstants.BUSINESS_EVENTS.GROUPS_CREATE,
+                constructEntityMap(BUSINESS_ENTITY.GROUP, 
commandProcessingResult));
+
+        return commandProcessingResult;
     }
 
     @Transactional
@@ -961,4 +979,10 @@ public class 
GroupingTypesWritePlatformServiceJpaRepositoryImpl implements Group
             }
         }
     }
+
+    private Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> 
constructEntityMap(final BUSINESS_ENTITY entityEvent, Object entity) {
+        Map<BUSINESS_ENTITY, Object> map = new HashMap<>(1);
+        map.put(entityEvent, entity);
+        return map;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
index 3b14a92..f5a78c2 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@@ -394,6 +394,8 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                     EntityTables.LOAN.getName(), 
StatusEnum.CREATE.getCode().longValue(),
                     EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), 
newLoanApplication.productId());
 
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.LOAN, 
newLoanApplication));
 
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index 5744b67..99af8cd 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -128,6 +128,7 @@ import org.springframework.util.CollectionUtils;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 
+
 @Service
 public class LoanWritePlatformServiceJpaRepositoryImpl implements 
LoanWritePlatformService {
 
@@ -1172,7 +1173,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         this.loanAccountDomainService.recalculateAccruals(loan);
         
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_CLOSE,
                 constructEntityMap(BUSINESS_ENTITY.LOAN, loan));
-        
+
         // disable all active standing instructions linked to the loan
         
this.loanAccountDomainService.disableStandingInstructionsLinkedToClosedLoan(loan);
         

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java
index 424b3ac..a21fe52 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductWritePlatformServiceJpaRepositoryImpl.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.loanproduct.service;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -35,6 +36,8 @@ import 
org.apache.fineract.infrastructure.entityaccess.service.FineractEntityAcc
 import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
 import org.apache.fineract.portfolio.charge.domain.Charge;
 import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
+import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
 import 
org.apache.fineract.portfolio.floatingrates.domain.FloatingRateRepositoryWrapper;
 import org.apache.fineract.portfolio.fund.domain.Fund;
@@ -43,6 +46,8 @@ import 
org.apache.fineract.portfolio.fund.exception.FundNotFoundException;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionProcessingStrategyRepository;
 import 
org.apache.fineract.portfolio.loanaccount.exception.LoanTransactionProcessingStrategyNotFoundException;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
 import 
org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
@@ -78,6 +83,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl 
implements LoanPro
     private final FineractEntityAccessUtil fineractEntityAccessUtil;
     private final FloatingRateRepositoryWrapper floatingRateRepository;
     private final LoanRepositoryWrapper loanRepositoryWrapper;
+    private final BusinessEventNotifierService businessEventNotifierService;
 
     @Autowired
     public LoanProductWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
@@ -88,7 +94,8 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl 
implements LoanPro
             final ProductToGLAccountMappingWritePlatformService 
accountMappingWritePlatformService,
             final FineractEntityAccessUtil fineractEntityAccessUtil,
             final FloatingRateRepositoryWrapper floatingRateRepository,
-            final LoanRepositoryWrapper loanRepositoryWrapper) {
+            final LoanRepositoryWrapper loanRepositoryWrapper,
+            final BusinessEventNotifierService businessEventNotifierService) {
         this.context = context;
         this.fromApiJsonDeserializer = fromApiJsonDeserializer;
         this.loanProductRepository = loanProductRepository;
@@ -100,6 +107,7 @@ public class 
LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
         this.fineractEntityAccessUtil = fineractEntityAccessUtil;
         this.floatingRateRepository = floatingRateRepository;
         this.loanRepositoryWrapper = loanRepositoryWrapper;
+        this.businessEventNotifierService = businessEventNotifierService;
     }
 
     @Transactional
@@ -139,6 +147,9 @@ public class 
LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
             
fineractEntityAccessUtil.checkConfigurationAndAddProductResrictionsForUserOffice(
                        
FineractEntityAccessType.OFFICE_ACCESS_TO_LOAN_PRODUCTS, 
                        loanproduct.getId());
+
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_PRODUCT_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.LOAN_PRODUCT, 
loanproduct));
             
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
@@ -332,4 +343,10 @@ public class 
LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
     private void logAsErrorUnexpectedDataIntegrityException(final Exception 
dve) {
         logger.error(dve.getMessage(), dve);
     }
+
+    private Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> 
constructEntityMap(final BusinessEventNotificationConstants.BUSINESS_ENTITY 
entityEvent, Object entity) {
+        Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> map = 
new HashMap<>(1);
+        map.put(entityEvent, entity);
+        return map;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
index 1da6e8f..cedcfdd 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
@@ -24,11 +24,7 @@ import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.recurri
 import static 
org.apache.fineract.portfolio.savings.DepositsApiConstants.transferInterestToSavingsParamName;
 
 import java.math.MathContext;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import javax.persistence.PersistenceException;
 
@@ -65,7 +61,9 @@ import 
org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
 import org.apache.fineract.portfolio.client.domain.Client;
 import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
 import org.apache.fineract.portfolio.client.exception.ClientNotActiveException;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
 import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
+import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.group.domain.Group;
 import org.apache.fineract.portfolio.group.domain.GroupRepository;
 import org.apache.fineract.portfolio.group.exception.CenterNotActiveException;
@@ -97,6 +95,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataAccessException;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
 
 @Service
 public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl 
implements DepositApplicationProcessWritePlatformService {
@@ -122,6 +122,7 @@ public class 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
     private final CalendarInstanceRepository calendarInstanceRepository;
     private final ConfigurationDomainService configurationDomainService;
     private final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository;
+    private final BusinessEventNotifierService businessEventNotifierService;
 
     @Autowired
     public 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl(final 
PlatformSecurityContext context,
@@ -136,7 +137,8 @@ public class 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
             final RecurringDepositAccountRepository 
recurringDepositAccountRepository,
             final AccountAssociationsRepository accountAssociationsRepository, 
final FromJsonHelper fromJsonHelper,
             final CalendarInstanceRepository calendarInstanceRepository, final 
ConfigurationDomainService configurationDomainService,
-            final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository) {
+            final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository,
+            final BusinessEventNotifierService businessEventNotifierService) {
         this.context = context;
         this.savingAccountRepository = savingAccountRepository;
         this.depositAccountAssembler = depositAccountAssembler;
@@ -156,6 +158,7 @@ public class 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
         this.calendarInstanceRepository = calendarInstanceRepository;
         this.configurationDomainService = configurationDomainService;
         this.accountNumberFormatRepository = accountNumberFormatRepository;
+        this.businessEventNotifierService = businessEventNotifierService;
     }
 
     /*
@@ -227,6 +230,9 @@ public class 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
 
             final Long savingsId = account.getId();
 
+            this.businessEventNotifierService.notifyBusinessEventWasExecuted( 
BUSINESS_EVENTS.FIXED_DEPOSIT_ACCOUNT_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.DEPOSIT_ACCOUNT, 
account));
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
                     .withEntityId(savingsId) //
@@ -285,6 +291,9 @@ public class 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
             account.validateApplicableInterestRate();
             this.savingAccountRepository.save(account);
 
+            this.businessEventNotifierService.notifyBusinessEventWasExecuted( 
BUSINESS_EVENTS.RECURRING_DEPOSIT_ACCOUNT_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.DEPOSIT_ACCOUNT, 
account));
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
                     .withEntityId(savingsId) //
@@ -769,4 +778,10 @@ public class 
DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
             }
         }
     }
+
+    private Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> 
constructEntityMap(final BUSINESS_ENTITY entityEvent, Object entity) {
+        Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> map = 
new HashMap<>(1);
+        map.put(entityEvent, entity);
+        return map;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
index 03409ed..e143c09 100755
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -382,6 +382,9 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
 
         }
         postInterest(account,postInterestAs,transactionDate);
+
+        
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SAVINGS_POST_INTEREST,
+                constructEntityMap(BUSINESS_ENTITY.SAVING, account));
         return new CommandProcessingResultBuilder() //
                 .withEntityId(savingsId) //
                 .withOfficeId(account.officeId()) //
@@ -682,7 +685,10 @@ public class 
SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
             }
 
         }
-        
+
+
+        
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SAVINGS_CLOSE,
+                constructEntityMap(BUSINESS_ENTITY.SAVING, account));
         // disable all standing orders linked to the savings account
         this.disableStandingInstructionsLinkedToClosedSavings(account);
         return new CommandProcessingResultBuilder() //

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
index 45056ca..5cabe1b 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl.java
@@ -181,6 +181,9 @@ public class 
SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
                     EntityTables.SAVING.getName(), 
StatusEnum.CREATE.getCode().longValue(),
                     EntityTables.SAVING.getForeignKeyColumnNameOnDatatable(), 
account.productId());
 
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SAVINGS_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.SAVING, account));
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(command.commandId()) //
                     .withEntityId(savingsId) //
@@ -362,6 +365,9 @@ public class 
SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
             }
         }
 
+        
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SAVINGS_APPROVE,
+                constructEntityMap(BUSINESS_ENTITY.SAVING, savingsAccount));
+
         return new CommandProcessingResultBuilder() //
                 .withCommandId(command.commandId()) //
                 .withEntityId(savingsId) //

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
index 7a2a422..90259ce 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -42,8 +42,12 @@ import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityEx
 import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
 import 
org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
 import org.apache.fineract.portfolio.client.domain.AccountNumberGenerator;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
+import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
 import org.apache.fineract.portfolio.note.domain.Note;
 import org.apache.fineract.portfolio.note.domain.NoteRepository;
 import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionEnumData;
@@ -75,6 +79,8 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
     private final JournalEntryWritePlatformService 
journalEntryWritePlatformService;
 
     private final NoteRepository noteRepository;
+
+    private final BusinessEventNotifierService businessEventNotifierService;
     
     @Autowired
     public ShareAccountWritePlatformServiceJpaRepositoryImpl(final 
ShareAccountDataSerializer accountDataSerializer,
@@ -83,14 +89,16 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             final AccountNumberGenerator accountNumberGenerator,
             final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository,
             final JournalEntryWritePlatformService 
journalEntryWritePlatformService,
-            final NoteRepository noteRepository) {
+            final NoteRepository noteRepository,
+            final BusinessEventNotifierService businessEventNotifierService) {
         this.accountDataSerializer = accountDataSerializer;
         this.shareAccountRepository = shareAccountRepository;
         this.shareProductRepository = shareProductRepository ;
         this.accountNumberGenerator = accountNumberGenerator;
         this.accountNumberFormatRepository = accountNumberFormatRepository;
         this.journalEntryWritePlatformService = 
journalEntryWritePlatformService;
-        this.noteRepository = noteRepository ;
+        this.noteRepository = noteRepository;
+        this.businessEventNotifierService = businessEventNotifierService;
     }
 
     @Override
@@ -101,6 +109,10 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             generateAccountNumber(account);
             
journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
                     account.getPendingForApprovalSharePurchaseTransactions()));
+
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SHARE_ACCOUNT_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.SHARE_ACCOUNT, 
account));
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(account.getId()) //
@@ -273,6 +285,10 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             this.shareProductRepository.save(shareProduct);
             
             
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
 journalTransactions));
+
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SHARE_ACCOUNT_APPROVE,
+                    constructEntityMap(BUSINESS_ENTITY.SHARE_ACCOUNT, 
account));
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(accountId) //
@@ -516,4 +532,10 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
         throw new 
PlatformDataIntegrityException("error.msg.shareaccount.unknown.data.integrity.issue",
                 "Unknown data integrity issue with resource.");
     }
+
+    private Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> 
constructEntityMap(final BusinessEventNotificationConstants.BUSINESS_ENTITY 
entityEvent, Object entity) {
+        Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> map = 
new HashMap<>(1);
+        map.put(entityEvent, entity);
+        return map;
+    }
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
index 2a310a2..1a4ff23 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
@@ -19,6 +19,7 @@
 package org.apache.fineract.portfolio.shareproducts.service;
 
 import java.math.BigDecimal;
+import java.util.HashMap;
 import java.util.Map;
 
 import javax.persistence.PersistenceException;
@@ -30,6 +31,10 @@ import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
 import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
 import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
 import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_ENTITY;
+import 
org.apache.fineract.portfolio.common.BusinessEventNotificationConstants.BUSINESS_EVENTS;
+import org.apache.fineract.portfolio.common.BusinessEventNotificationConstants;
+import 
org.apache.fineract.portfolio.common.service.BusinessEventNotifierService;
 import 
org.apache.fineract.portfolio.shareproducts.constants.ShareProductApiConstants;
 import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
 import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividendPayOutDetails;
@@ -53,19 +58,22 @@ public class 
ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareP
     private final ShareProductDividentPayOutDetailsRepositoryWrapper 
shareProductDividentPayOutDetailsRepository;
     private final ShareProductDividendAssembler shareProductDividendAssembler;
     private final ProductToGLAccountMappingWritePlatformService 
accountMappingWritePlatformService;
+    private final BusinessEventNotifierService businessEventNotifierService;
 
     @Autowired
     public ShareProductWritePlatformServiceJpaRepositoryImpl(final 
ShareProductRepositoryWrapper repository,
             final ShareProductDataSerializer serializer, final FromJsonHelper 
fromApiJsonHelper,
             final ShareProductDividentPayOutDetailsRepositoryWrapper 
shareProductDividentPayOutDetailsRepositor,
             final ShareProductDividendAssembler shareProductDividendAssembler,
-            final ProductToGLAccountMappingWritePlatformService 
accountMappingWritePlatformService) {
+            final ProductToGLAccountMappingWritePlatformService 
accountMappingWritePlatformService,
+            final BusinessEventNotifierService businessEventNotifierService) {
         this.repository = repository;
         this.serializer = serializer;
         this.fromApiJsonHelper = fromApiJsonHelper;
         this.shareProductDividentPayOutDetailsRepository = 
shareProductDividentPayOutDetailsRepositor;
         this.shareProductDividendAssembler = shareProductDividendAssembler;
         this.accountMappingWritePlatformService = 
accountMappingWritePlatformService;
+        this.businessEventNotifierService = businessEventNotifierService;
     }
 
     @Override
@@ -140,6 +148,10 @@ public class 
ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareP
                     "No eligible shares for creating dividends"); }
             
this.shareProductDividentPayOutDetailsRepository.save(dividendPayOutDetails);
 
+
+            
this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.SHARE_PRODUCT_DIVIDENDS_CREATE,
+                    constructEntityMap(BUSINESS_ENTITY.SHARE_PRODUCT, 
productId));
+
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(productId) //
@@ -204,4 +216,10 @@ public class 
ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareP
                 "Unknown data integrity issue with resource.");
     }
 
+    private Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> 
constructEntityMap(final BusinessEventNotificationConstants.BUSINESS_ENTITY 
entityEvent, Object entity) {
+        Map<BusinessEventNotificationConstants.BUSINESS_ENTITY, Object> map = 
new HashMap<>(1);
+        map.put(entityEvent, entity);
+        return map;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/resources/META-INF/spring/appContext.xml 
b/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
index dffd1b2..e348d8a 100644
--- a/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
+++ b/fineract-provider/src/main/resources/META-INF/spring/appContext.xml
@@ -52,6 +52,7 @@
                                                                                
  org.apache.fineract.portfolio.*,
                                                                                
  org.apache.fineract.useradministration.*,
                                                                                
  org.apache.fineract.mix.*,
+                                                                               
  org.apache.fineract.notification.*,
                                                                                
  org.apache.fineract.template.*,
                                                                                
  org.apache.fineract.template.service.*,
                                                                                
  org.apache.fineract.useradministration.*,
@@ -82,6 +83,7 @@
        <jpa:repositories base-package="org.apache.fineract.template.domain" />
        <jpa:repositories 
base-package="org.apache.fineract.infrastructure.campaigns.sms.domain" />
        <jpa:repositories base-package="org.apache.fineract.adhocquery.domain" 
/>
+       <jpa:repositories 
base-package="org.apache.fineract.notification.domain"/>
        
        <import resource="infrastructure.xml" />
 
@@ -96,4 +98,6 @@
        </bean>
 
        <import resource="spmContext.xml"/>
+
+       <import resource="notificationContext.xml"/>
 </beans>

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/resources/META-INF/spring/notificationContext.xml
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/resources/META-INF/spring/notificationContext.xml 
b/fineract-provider/src/main/resources/META-INF/spring/notificationContext.xml
new file mode 100644
index 0000000..5ca57e7
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/META-INF/spring/notificationContext.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd";>
+
+    <bean id="amqConnectionFactory" 
class="org.apache.activemq.ActiveMQConnectionFactory">
+        <constructor-arg index="0" value="tcp://localhost:61616" />
+    </bean>
+
+    <bean id="connectionFactory" 
class="org.springframework.jms.connection.CachingConnectionFactory">
+        <constructor-arg ref="amqConnectionFactory"/>
+    </bean>
+
+    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
+        <property name="connectionFactory" ref="connectionFactory"/>
+    </bean>
+
+    <bean id="messageListenerContainer" 
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
+        <property name="connectionFactory" ref="connectionFactory" />
+        <property name="destinationName" value="NotificationQueue"/>
+        <property name="messageListener" ref="notificationEventListener" />
+    </bean>
+</beans>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/main/resources/sql/migrations/core_db/V334__notification_module_tables.sql
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/resources/sql/migrations/core_db/V334__notification_module_tables.sql
 
b/fineract-provider/src/main/resources/sql/migrations/core_db/V334__notification_module_tables.sql
new file mode 100644
index 0000000..8fa6dd6
--- /dev/null
+++ 
b/fineract-provider/src/main/resources/sql/migrations/core_db/V334__notification_module_tables.sql
@@ -0,0 +1,48 @@
+--
+-- 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.
+--
+
+CREATE TABLE IF NOT EXISTS `notification_generator` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `object_type` text,
+  `object_identifier` bigint(20) DEFAULT NULL,
+  `action` text,
+  `actor` bigint(20),
+  `is_system_generated` tinyint(1) DEFAULT '0',
+  `notification_content` text,
+  `created_at` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
+
+
+CREATE TABLE IF NOT EXISTS `notification_mapper` (
+  `id` bigint(20) NOT NULL AUTO_INCREMENT,
+  `notification_id` bigint(20) DEFAULT NULL,
+  `user_id` bigint(20) DEFAULT NULL,
+  `is_read` tinyint(1) DEFAULT '0',
+  `created_at` datetime DEFAULT NULL,
+  PRIMARY KEY (`id`),
+  KEY `notification_mapper` (`user_id`),
+  KEY `notification_id` (`notification_id`)
+) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
+
+ALTER TABLE `notification_mapper`
+  ADD CONSTRAINT `notification_mapper_ibfk_2` FOREIGN KEY (`user_id`) 
REFERENCES `m_appuser` (`id`),
+  ADD CONSTRAINT `notification_mapper_ibfk_3` FOREIGN KEY (`notification_id`) 
REFERENCES `notification_generator` (`id`);
+
+

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/test/java/org/apache/fineract/notification/Listener.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/notification/Listener.java
 
b/fineract-provider/src/test/java/org/apache/fineract/notification/Listener.java
new file mode 100644
index 0000000..866eadd
--- /dev/null
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/notification/Listener.java
@@ -0,0 +1,33 @@
+package org.apache.fineract.notification;
+
+/**
+ * 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 org.springframework.jms.listener.SessionAwareMessageListener;
+
+import javax.jms.*;
+
+public class Listener implements SessionAwareMessageListener {
+
+    @Override
+    public void onMessage(Message message, Session session) throws 
JMSException {
+        TextMessage msg = (TextMessage) message;
+        System.out.println("Received: " + msg.getText());
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/test/java/org/apache/fineract/notification/ListenerTest.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/notification/ListenerTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/notification/ListenerTest.java
new file mode 100644
index 0000000..7f94379
--- /dev/null
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/notification/ListenerTest.java
@@ -0,0 +1,52 @@
+package org.apache.fineract.notification;
+
+/**
+ * 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 org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import javax.jms.JMSException;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ListenerTest {
+
+    private Listener listener;
+    private Session session;
+    private TextMessage textMessageMock;
+
+    @Before
+    public void setUp() {
+        listener = new Listener();
+        session = Mockito.mock(Session.class);
+        textMessageMock = Mockito.mock(TextMessage.class);
+    }
+
+    @Test
+    public void testListener() throws JMSException {
+        Mockito.when(textMessageMock.getText()).thenReturn("content");
+        listener.onMessage(textMessageMock, session);
+        Mockito.verify(textMessageMock).getText();
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/test/java/org/apache/fineract/notification/SenderTest.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/notification/SenderTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/notification/SenderTest.java
new file mode 100644
index 0000000..1a7e091
--- /dev/null
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/notification/SenderTest.java
@@ -0,0 +1,77 @@
+package org.apache.fineract.notification;
+
+/**
+ * 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.mockrunner.mock.jms.MockQueue;
+import org.apache.fineract.notification.data.NotificationData;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+
+@ContextConfiguration(locations = {
+        "classpath:META-INF/testNotificationContext.xml",
+})
+@RunWith(SpringJUnit4ClassRunner.class)
+public class SenderTest {
+
+    @Autowired
+    private JmsTemplate jmsTemplate;
+
+    @Autowired
+    private MockQueue mockQueue;
+
+    @Test
+    public void notificationCreation() {
+
+        String objectType = "CLIENT";
+        Long objectIdentifier = 1L;
+        String action = "created";
+        Long actorId = 1L;
+        String notificationContent = "A client was created";
+
+        NotificationData notificationData = new NotificationData(
+                objectType,
+                objectIdentifier,
+                action,
+                actorId,
+                notificationContent,
+                false,
+                null,
+                null,
+                null
+        );
+
+        jmsTemplate.send(mockQueue, new MessageCreator() {
+            @Override
+            public Message createMessage(Session session) throws JMSException {
+                System.out.println("Message send successfully");
+                return session.createObjectMessage(notificationData);
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/c60c6601/fineract-provider/src/test/java/org/apache/fineract/notification/StorageTest.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/notification/StorageTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/notification/StorageTest.java
new file mode 100644
index 0000000..59ae708
--- /dev/null
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/notification/StorageTest.java
@@ -0,0 +1,130 @@
+package org.apache.fineract.notification;
+
+/**
+ * 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 org.apache.fineract.notification.domain.Notification;
+import org.apache.fineract.notification.domain.NotificationMapper;
+import 
org.apache.fineract.notification.service.NotificationGeneratorReadRepositoryWrapper;
+import 
org.apache.fineract.notification.service.NotificationGeneratorWritePlatformService;
+import 
org.apache.fineract.notification.service.NotificationMapperWritePlatformService;
+import 
org.apache.fineract.notification.service.NotificationWritePlatformServiceImpl;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.AppUserRepository;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class StorageTest {
+
+    private NotificationWritePlatformServiceImpl 
notificationWritePlatformServiceImpl;
+
+    @Mock
+    private NotificationGeneratorReadRepositoryWrapper 
notificationGeneratorReadRepositoryWrapper;
+
+    @Mock
+    private NotificationGeneratorWritePlatformService 
notificationGeneratorWritePlatformService;
+
+    @Mock
+    private NotificationMapperWritePlatformService 
notificationMapperWritePlatformService;
+
+    @Mock
+    private AppUserRepository appUserRepository;
+
+    @Before
+    public void setUp() {
+        notificationWritePlatformServiceImpl = new 
NotificationWritePlatformServiceImpl(
+                notificationGeneratorWritePlatformService,
+                notificationGeneratorReadRepositoryWrapper,
+                appUserRepository,
+                notificationMapperWritePlatformService);
+    }
+
+    @Test
+    public void testNotificationStorage() {
+
+        Long userId = 1L;
+        String objectType = "CLIENT";
+        Long objectIdentifier = 1L;
+        String action = "created";
+        Long actor = 1L;
+        String notificationContent = "A client was created";
+        boolean isSystemGenerated = false;
+
+        Notification notification = new Notification(
+                objectType,
+                objectIdentifier,
+                action,
+                actor,
+                isSystemGenerated,
+                notificationContent,
+                getCurrentDateTime()
+        );
+
+
+        AppUser appUser = this.appUserRepository.findOne(1L);
+
+        NotificationMapper notificationMapper = new NotificationMapper(
+                notification,
+                appUser,
+                false,
+                getCurrentDateTime()
+        );
+
+
+        
when(this.notificationGeneratorWritePlatformService.create(refEq(notification))).thenReturn(1L);
+
+        when(this.appUserRepository.findOne(userId)).thenReturn(appUser);
+
+        
when(this.notificationGeneratorReadRepositoryWrapper.findById(1L)).thenReturn(notification);
+
+        
when(this.notificationMapperWritePlatformService.create(refEq(notificationMapper))).thenReturn(1L);
+
+        Long actualGeneratedNotificationId =
+                notificationWritePlatformServiceImpl.notify(
+                        userId,
+                        objectType,
+                        objectIdentifier,
+                        action,
+                        actor,
+                        notificationContent,
+                        isSystemGenerated
+                );
+
+        verify(this.notificationGeneratorWritePlatformService, 
times(1)).create(refEq(notification));
+        verify(this.notificationMapperWritePlatformService, 
times(1)).create(refEq(notificationMapper));
+        verify(this.notificationGeneratorReadRepositoryWrapper, 
times(1)).findById(1L);
+        assertEquals(actualGeneratedNotificationId, new Long(1));
+    }
+
+    private String getCurrentDateTime() {
+        Date date = new Date();
+        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss");
+        return formatter.format(date);
+    }
+}

Reply via email to