You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by GitBox <gi...@apache.org> on 2018/09/01 15:45:57 UTC

[GitHub] ebenezergraham closed pull request #5: Unit and component Tests, Rest and command updates and Bug Fixes

ebenezergraham closed pull request #5: Unit and component Tests,Rest and command updates and Bug Fixes
URL: https://github.com/apache/fineract-cn-notifications/pull/5
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..99b514a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+.gradle
+.idea
+build/
+target/
+detail
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+*.iml
+
+*.log
+
+*.toDelete
diff --git a/HEADER b/HEADER
new file mode 100644
index 0000000..90705e0
--- /dev/null
+++ b/HEADER
@@ -0,0 +1,16 @@
+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.
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed 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.
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..41f69b8
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Fineract CN Notification
+Copyright [2017-2018] The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/api/build.gradle b/api/build.gradle
new file mode 100644
index 0000000..5b9924a
--- /dev/null
+++ b/api/build.gradle
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath 'io.spring.gradle:dependency-management-plugin:0.6.0.RELEASE'
+    }
+}
+
+plugins {
+    id "com.github.hierynomus.license" version "0.13.1"
+    id("org.nosphere.apache.rat") version "0.3.1"
+}
+
+apply from: '../shared.gradle'
+
+dependencies {
+    compile(
+            [group: 'org.springframework.cloud', name: 'spring-cloud-starter-feign'],
+            [group: 'org.apache.fineract.cn', name: 'api', version: versions.frameworkapi],
+            [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator],
+            [group: 'org.hibernate', name: 'hibernate-validator-annotation-processor', version: versions.validator]
+    )
+
+    testCompile(
+            [group: 'org.apache.fineract.cn', name: 'test', version: versions.frameworktest],
+    )
+}
+
+publishing {
+    publications {
+        api(MavenPublication) {
+            from components.java
+            groupId project.group
+            artifactId project.name
+            version project.version
+        }
+    }
+}
diff --git a/api/settings.gradle b/api/settings.gradle
new file mode 100644
index 0000000..491f745
--- /dev/null
+++ b/api/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+rootProject.name = 'api'
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/PermittableGroupIds.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/PermittableGroupIds.java
new file mode 100644
index 0000000..a5c9de2
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/PermittableGroupIds.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.cn.notification.api.v1;
+
+@SuppressWarnings("unused")
+public interface PermittableGroupIds {
+	String SELF_MANAGEMENT = "notification__v1__self";
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/client/ConfigurationNotFoundException.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/client/ConfigurationNotFoundException.java
new file mode 100644
index 0000000..4f5d185
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/client/ConfigurationNotFoundException.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.client;
+
+import org.apache.fineract.cn.api.util.NotFoundException;
+
+public final class ConfigurationNotFoundException extends NotFoundException {
+	
+	public ConfigurationNotFoundException(String reason) {
+		super(reason);
+	}
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/client/NotificationManager.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/client/NotificationManager.java
new file mode 100644
index 0000000..b169cfd
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/client/NotificationManager.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.client;
+
+import org.apache.fineract.cn.api.util.CustomFeignClientsConfiguration;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@SuppressWarnings("unused")
+@FeignClient(value = "notification-v1", path = "/notification/v1", configuration = CustomFeignClientsConfiguration.class)
+public interface NotificationManager {
+	
+	@RequestMapping(
+			value = "/notification/sms/active",
+			method = RequestMethod.GET,
+			produces = MediaType.ALL_VALUE,
+			consumes = MediaType.APPLICATION_JSON_VALUE)
+	SMSConfiguration findAllActiveSMSConfigurationEntities();
+	
+	@RequestMapping(
+			value = "/notification/email/active",
+			method = RequestMethod.GET,
+			produces = MediaType.ALL_VALUE,
+			consumes = MediaType.APPLICATION_JSON_VALUE)
+	EmailConfiguration findAllActiveEmailConfigurationEntities();
+	
+	@RequestMapping(
+			value = "/notification/sms/create",
+			method = RequestMethod.POST,
+			produces = MediaType.APPLICATION_JSON_VALUE,
+			consumes = MediaType.APPLICATION_JSON_VALUE
+	)
+	void createSMSConfiguration(final SMSConfiguration smsConfiguration);
+	
+	@RequestMapping(
+			value = "/notification/email/create",
+			method = RequestMethod.POST,
+			produces = MediaType.APPLICATION_JSON_VALUE,
+			consumes = MediaType.APPLICATION_JSON_VALUE
+	)
+	void createEmailConfiguration(final EmailConfiguration emailConfiguration);
+	
+	@RequestMapping(
+			value = "/notification/sms/{identifier}",
+			method = RequestMethod.GET,
+			produces = MediaType.APPLICATION_JSON_VALUE,
+			consumes = MediaType.APPLICATION_JSON_VALUE
+	)
+	SMSConfiguration findSMSConfigurationByIdentifier(@PathVariable("identifier") final String identifier);
+	
+	@RequestMapping(
+			value = "/notification/email/{identifier}",
+			method = RequestMethod.GET,
+			produces = MediaType.APPLICATION_JSON_VALUE,
+			consumes = MediaType.APPLICATION_JSON_VALUE
+	)
+	EmailConfiguration findEmailConfigurationByIdentifier(@PathVariable("identifier") final String identifier);
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/EmailConfiguration.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/EmailConfiguration.java
new file mode 100644
index 0000000..6b95afd
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/EmailConfiguration.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.fineract.cn.lang.validation.constraints.ValidIdentifier;
+import org.hibernate.validator.constraints.Length;
+
+import java.util.Objects;
+
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class EmailConfiguration {
+	@ValidIdentifier
+	@Length(max = 11)
+	private String identifier;
+	@Length(max = 45)
+	private String host;
+	@Length(max = 45)
+	private String port;
+	@Length(max = 45)
+	private String protocol;
+	@Length(max = 45)
+	private String username;
+	@Length(max = 255)
+	private String app_password;
+	@Length(max = 45)
+	private String smtp_auth;
+	@Length(max = 45)
+	private String start_tls;
+	@Length(max = 45)
+	private String state;
+	
+	public EmailConfiguration() {
+		super();
+	}
+	
+	public static EmailConfiguration create(String identifier,
+	                                        String host, String port,
+	                                        String protocol, String username,
+	                                        String app_password, String smtp_auth,
+	                                        String start_tls, String state) {
+		EmailConfiguration emailConfiguration = new EmailConfiguration();
+		emailConfiguration.setIdentifier(identifier);
+		emailConfiguration.setHost(host);
+		emailConfiguration.setPort(port);
+		emailConfiguration.setProtocol(protocol);
+		emailConfiguration.setUsername(username);
+		emailConfiguration.setApp_password(app_password);
+		emailConfiguration.setSmtp_auth(smtp_auth);
+		emailConfiguration.setStart_tls(start_tls);
+		emailConfiguration.setState(state);
+		return emailConfiguration;
+	}
+	
+	public String getIdentifier() {
+		return identifier;
+	}
+	
+	public void setIdentifier(String identifier) {
+		this.identifier = identifier;
+	}
+	
+	public String getHost() {
+		return host;
+	}
+	
+	public void setHost(String host) {
+		this.host = host;
+	}
+	
+	public String getPort() {
+		return port;
+	}
+	
+	public void setPort(String port) {
+		this.port = port;
+	}
+	
+	public String getProtocol() {
+		return protocol;
+	}
+	
+	public void setProtocol(String protocol) {
+		this.protocol = protocol;
+	}
+	
+	public String getUsername() {
+		return username;
+	}
+	
+	public void setUsername(String username) {
+		this.username = username;
+	}
+	
+	public String getApp_password() {
+		return app_password;
+	}
+	
+	public void setApp_password(String app_password) {
+		this.app_password = app_password;
+	}
+	
+	public String getSmtp_auth() {
+		return smtp_auth;
+	}
+	
+	public void setSmtp_auth(String smtp_auth) {
+		this.smtp_auth = smtp_auth;
+	}
+	
+	public String getStart_tls() {
+		return start_tls;
+	}
+	
+	public void setStart_tls(String start_tls) {
+		this.start_tls = start_tls;
+	}
+	
+	public String getState() {
+		return state;
+	}
+	
+	public void setState(String state) {
+		this.state = state;
+	}
+	
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		EmailConfiguration that = (EmailConfiguration) o;
+		return Objects.equals(identifier, that.identifier) &&
+				Objects.equals(host, that.host) &&
+				Objects.equals(port, that.port) &&
+				Objects.equals(protocol, that.protocol) &&
+				Objects.equals(username, that.username) &&
+				Objects.equals(app_password, that.app_password) &&
+				Objects.equals(smtp_auth, that.smtp_auth) &&
+				Objects.equals(start_tls, that.start_tls) &&
+				Objects.equals(state, that.state);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(identifier, host, port, protocol, username, app_password, smtp_auth, start_tls, state);
+	}
+	
+	@Override
+	public String toString() {
+		return "EmailConfiguration{" +
+				"identifier='" + identifier + '\'' +
+				", host='" + host + '\'' +
+				", port='" + port + '\'' +
+				", protocol='" + protocol + '\'' +
+				", username='" + username + '\'' +
+				", app_password='" + app_password + '\'' +
+				", smtp_auth='" + smtp_auth + '\'' +
+				", start_tls='" + start_tls + '\'' +
+				", state='" + state + '\'' +
+				'}';
+	}
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/EmailPage.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/EmailPage.java
new file mode 100644
index 0000000..f57ee35
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/EmailPage.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import java.util.List;
+import java.util.Objects;
+
+public class EmailPage {
+	
+	private List<EmailConfiguration> emailConfigurations;
+	private Integer totalPages;
+	private Long totalElements;
+	
+	public EmailPage() {
+		super();
+	}
+	
+	public List<EmailConfiguration> getEmailConfiguration() {
+		return this.emailConfigurations;
+	}
+	
+	public void setEmailConfiguration(final List<EmailConfiguration> emailConfiguration) {
+		this.emailConfigurations = emailConfigurations;
+	}
+	
+	public Integer getTotalPages() {
+		return this.totalPages;
+	}
+	
+	public void setTotalPages(final Integer totalPages) {
+		this.totalPages = totalPages;
+	}
+	
+	public Long getTotalElements() {
+		return this.totalElements;
+	}
+	
+	public void setTotalElements(final Long totalElements) {
+		this.totalElements = totalElements;
+	}
+	
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		EmailPage emailPage = (EmailPage) o;
+		return Objects.equals(emailConfigurations, emailPage.emailConfigurations) &&
+				Objects.equals(totalPages, emailPage.totalPages) &&
+				Objects.equals(totalElements, emailPage.totalElements);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(emailConfigurations, totalPages, totalElements);
+	}
+	
+	@Override
+	public String toString() {
+		return "EmailPage{" +
+				"emailConfigurations=" + emailConfigurations +
+				", totalPages=" + totalPages +
+				", totalElements=" + totalElements +
+				'}';
+	}
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/Event.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/Event.java
new file mode 100644
index 0000000..cb3fc5f
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/Event.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+/*
+ebenezergraham created on 8/19/18
+*/
+
+import java.util.Objects;
+
+public class Event {
+	private final String identifier;
+	private boolean enabled;
+	
+	public Event(String identifier, boolean enabled) {
+		super();
+		this.identifier = identifier;
+		this.enabled = enabled;
+	}
+	
+	public String getIdentifier() {
+		return identifier;
+	}
+	
+	public boolean isEnabled() {
+		return enabled;
+	}
+	
+	public void setEnabled(boolean state) {
+		this.enabled = state;
+	}
+	
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		Event event = (Event) o;
+		return enabled == event.enabled &&
+				Objects.equals(identifier, event.identifier);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(identifier, enabled);
+	}
+	
+	@Override
+	public String toString() {
+		return "Event{" +
+				"identifier='" + identifier + '\'' +
+				", enabled=" + enabled +
+				'}';
+	}
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/SMSConfiguration.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/SMSConfiguration.java
new file mode 100644
index 0000000..dd76852
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/SMSConfiguration.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.fineract.cn.lang.validation.constraints.ValidIdentifier;
+import org.hibernate.validator.constraints.Length;
+
+import java.util.Objects;
+
+@SuppressWarnings({"WeakerAccess", "unused"})
+public class SMSConfiguration {
+	@ValidIdentifier
+	@Length(max = 45)
+	private String identifier;
+	@Length(max = 255)
+	private String auth_token;
+	@Length(max = 255)
+	private String account_sid;
+	@Length(max = 45)
+	private String sender_number;
+	@Length(max = 45)
+	private String state;
+	
+	public SMSConfiguration() {
+		super();
+	}
+	
+	public static SMSConfiguration create(String identifier,
+	                                      String auth_token,
+	                                      String account_sid,
+	                                      String sender_number,
+	                                      String state) {
+		SMSConfiguration smsconfiguration = new SMSConfiguration();
+		smsconfiguration.setIdentifier(identifier);
+		smsconfiguration.setAuth_token(auth_token);
+		smsconfiguration.setAccount_sid(account_sid);
+		smsconfiguration.setSender_number(sender_number);
+		smsconfiguration.setState(state);
+		return smsconfiguration;
+	}
+	
+	public String getIdentifier() {
+		return identifier;
+	}
+	
+	public void setIdentifier(String identifier) {
+		this.identifier = identifier;
+	}
+	
+	public String getAuth_token() {
+		return auth_token;
+	}
+	
+	public void setAuth_token(String auth_token) {
+		this.auth_token = auth_token;
+	}
+	
+	public String getAccount_sid() {
+		return account_sid;
+	}
+	
+	public void setAccount_sid(String account_sid) {
+		this.account_sid = account_sid;
+	}
+	
+	public String getSender_number() {
+		return sender_number;
+	}
+	
+	public void setSender_number(String sender_number) {
+		this.sender_number = sender_number;
+	}
+	
+	public String getState() {
+		return state;
+	}
+	
+	public void setState(String state) {
+		this.state = state;
+	}
+	
+	public String getType() {
+		return null;
+	}
+	
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		SMSConfiguration that = (SMSConfiguration) o;
+		return Objects.equals(identifier, that.identifier) &&
+				Objects.equals(auth_token, that.auth_token) &&
+				Objects.equals(account_sid, that.account_sid) &&
+				Objects.equals(state, that.state);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(identifier, auth_token, auth_token, account_sid, state);
+	}
+	
+	@Override
+	public String toString() {
+		return "SMSConfiguration{" +
+				"identifier='" + identifier + '\'' +
+				", auth_token='" + auth_token + '\'' +
+				", account_sid='" + account_sid + '\'' +
+				", sender_number='" + sender_number + '\'' +
+				", state='" + state + '\'' +
+				'}';
+	}
+	
+	private enum State {
+		ACTIVE,
+		DEACTIVATED;
+		
+		State() {
+		}
+	}
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/SMSPage.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/SMSPage.java
new file mode 100644
index 0000000..9e7ef8d
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/domain/SMSPage.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import java.util.List;
+import java.util.Objects;
+
+public class SMSPage {
+	
+	private List<SMSConfiguration> smsConfigurations;
+	private Integer totalPages;
+	private Long totalElements;
+	
+	public SMSPage() {
+		super();
+	}
+	
+	public List<SMSConfiguration> getSmsConfigurations() {
+		return this.smsConfigurations;
+	}
+	
+	public void setSmsConfigurations(final List<SMSConfiguration> smsConfigurations) {
+		this.smsConfigurations = smsConfigurations;
+	}
+	
+	public Integer getTotalPages() {
+		return this.totalPages;
+	}
+	
+	public void setTotalPages(final Integer totalPages) {
+		this.totalPages = totalPages;
+	}
+	
+	public Long getTotalElements() {
+		return this.totalElements;
+	}
+	
+	public void setTotalElements(final Long totalElements) {
+		this.totalElements = totalElements;
+	}
+	
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		SMSPage smsPage = (SMSPage) o;
+		return Objects.equals(smsConfigurations, smsPage.smsConfigurations) &&
+				Objects.equals(totalPages, smsPage.totalPages) &&
+				Objects.equals(totalElements, smsPage.totalElements);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(smsConfigurations, totalPages, totalElements);
+	}
+	
+	@Override
+	public String toString() {
+		return "SMSPage{" +
+				"smsConfigurations=" + smsConfigurations +
+				", totalPages=" + totalPages +
+				", totalElements=" + totalElements +
+				'}';
+	}
+}
diff --git a/api/src/main/java/org/apache/fineract/cn/notification/api/v1/events/NotificationEventConstants.java b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/events/NotificationEventConstants.java
new file mode 100644
index 0000000..f4d1be1
--- /dev/null
+++ b/api/src/main/java/org/apache/fineract/cn/notification/api/v1/events/NotificationEventConstants.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.events;
+
+@SuppressWarnings("unused")
+public interface NotificationEventConstants {
+	
+	String DESTINATION = "notification-v1";
+	String SELECTOR_NAME = "action";
+	String INITIALIZE = "initialize";
+	
+	String POST_SMS_CONFIGURATION = "post-sms-configuration";
+	String POST_EMAIL_CONFIGURATION = "post-email-configuration";
+	String POST_SMS_NOTIFICATION = "post-sms-notification";
+	String POST_EMAIL_NOTIFICATION = "post-email-notification";
+	
+	String POST_ENABLE_CUSTOMER_CREATED_EVENT = "post-enable-customer-created-event";
+	String POST_ENABLE_CUSTOMER_UPDATED_EVENT = "post-enable-customer-updated-event";
+	String POST_ENABLE_CUSTOMER_CLOSED_EVENT = "post-enable-customer-closed-event";
+	String POST_ENABLE_CUSTOMER_LOCKED_EVENT = "post-enable-customer-locked-event";
+	String POST_ENABLE_CUSTOMER_ACTIVATED_EVENT = "post-enable-customer-activated-event";
+	String POST_ENABLE_CUSTOMER__EVENT = "post-enable-customer--event";
+	
+	String SELECTOR_INITIALIZE = SELECTOR_NAME + " = '" + INITIALIZE + "'";
+	String SELECTOR_POST_SMS_CONFIGURATION = SELECTOR_NAME + " = '" + POST_SMS_CONFIGURATION + "'";
+	String SELECTOR_POST_EMAIL_CONFIGURATION = SELECTOR_NAME + " = '" + POST_EMAIL_CONFIGURATION + "'";
+	String SELECTOR_POST_SMS_NOTIFICATION = SELECTOR_NAME + " = '" + POST_SMS_NOTIFICATION + "'";
+	String SELECTOR_POST_EMAIL_NOTIFICATION = SELECTOR_NAME + " = '" + POST_EMAIL_NOTIFICATION + "'";
+}
diff --git a/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EmailConfigurationTest.java b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EmailConfigurationTest.java
new file mode 100644
index 0000000..294877a
--- /dev/null
+++ b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EmailConfigurationTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.fineract.cn.test.domain.ValidationTest;
+import org.apache.fineract.cn.test.domain.ValidationTestCase;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class EmailConfigurationTest extends ValidationTest<EmailConfiguration> {
+	
+	public EmailConfigurationTest(ValidationTestCase<EmailConfiguration> testCase) {
+		super(testCase);
+	}
+	
+	@Parameterized.Parameters
+	public static Collection testCases() {
+		final Collection<ValidationTestCase> ret = new ArrayList<>();
+		ret.add(new ValidationTestCase<EmailConfiguration>("basicCase")
+				.adjustment(x -> {
+				})
+				.valid(true));
+		ret.add(new ValidationTestCase<EmailConfiguration>("nullIdentifier")
+				.adjustment(x -> x.setIdentifier(null))
+				.valid(false));
+		ret.add(new ValidationTestCase<EmailConfiguration>("tooShortIdentifier")
+				.adjustment(x -> x.setIdentifier("z"))
+				.valid(false));
+		return ret;
+	}
+	
+	
+	protected EmailConfiguration createValidTestSubject() {
+		return EmailConfiguration.create("EmailTest",
+				"smtp.google.com",
+				"123",
+				"example",
+				"egraham",
+				"asdfaegw4t3rwg5w",
+				"true",
+				"true",
+				"ACTIVE");
+	}
+	
+	
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EmailPageTest.java b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EmailPageTest.java
new file mode 100644
index 0000000..f871958
--- /dev/null
+++ b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EmailPageTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.fineract.cn.test.domain.ValidationTest;
+import org.apache.fineract.cn.test.domain.ValidationTestCase;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class EmailPageTest extends ValidationTest<EmailPage> {
+	
+	EmailConfiguration emailConfiguration;
+	
+	public EmailPageTest(ValidationTestCase<EmailPage> testCase) {
+		super(testCase);
+	}
+	
+	@Parameterized.Parameters
+	public static Collection testCases() {
+		final Collection<ValidationTestCase> ret = new ArrayList<>();
+		ret.add(new ValidationTestCase<EmailPage>("basicCase")
+				.adjustment(x -> {
+				})
+				.valid(true));
+		ret.add(new ValidationTestCase<EmailPage>("getEmailConfiguration")
+				.adjustment(x -> x.getEmailConfiguration())
+				.valid(true));
+		return ret;
+	}
+	
+	@Override
+	protected EmailPage createValidTestSubject() {
+		EmailPage emailPage = new EmailPage();
+		emailConfiguration = new EmailConfiguration();
+		emailConfiguration.create("EmailTest",
+				"smtp.google.com",
+				"123",
+				"example",
+				"ebez",
+				"asdfaegw4t3rwg5w",
+				"true",
+				"true",
+				"ACTIVE");
+		emailPage.setEmailConfiguration(Arrays.asList(emailConfiguration));
+		return emailPage;
+	}
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EventTest.java b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EventTest.java
new file mode 100644
index 0000000..6983f14
--- /dev/null
+++ b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/EventTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.fineract.cn.test.domain.ValidationTest;
+import org.apache.fineract.cn.test.domain.ValidationTestCase;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class EventTest extends ValidationTest<Event> {
+	
+	public EventTest(ValidationTestCase<Event> testCase) {
+		super(testCase);
+	}
+	
+	@Parameterized.Parameters
+	public static Collection testCases() {
+		final Collection<ValidationTestCase> ret = new ArrayList<>();
+		ret.add(new ValidationTestCase<Event>("basicCase")
+				.adjustment(x -> {
+				})
+				.valid(true));
+		ret.add(new ValidationTestCase<Event>("nullIdentifier")
+				.adjustment(x -> x.getIdentifier().equals("customerCreated"))
+				.valid(true));
+		ret.add(new ValidationTestCase<Event>("Is Enabled")
+				.adjustment(x -> x.isEnabled())
+				.valid(true));
+		return ret;
+	}
+	
+	@Override
+	protected Event createValidTestSubject() {
+		return new Event("customerCreated", true);
+	}
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/SMSConfigurationTest.java b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/SMSConfigurationTest.java
new file mode 100644
index 0000000..9b3b0c7
--- /dev/null
+++ b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/SMSConfigurationTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.test.domain.ValidationTest;
+import org.apache.fineract.cn.test.domain.ValidationTestCase;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class SMSConfigurationTest extends ValidationTest<SMSConfiguration> {
+	
+	public SMSConfigurationTest(ValidationTestCase<SMSConfiguration> testCase) {
+		super(testCase);
+	}
+	
+	@Parameterized.Parameters
+	public static Collection testCases() {
+		final Collection<ValidationTestCase> ret = new ArrayList<>();
+		ret.add(new ValidationTestCase<SMSConfiguration>("basicCase")
+				.adjustment(x -> {
+				})
+				.valid(false));
+		ret.add(new ValidationTestCase<SMSConfiguration>("nullIdentifier")
+				.adjustment(x -> x.setIdentifier(null))
+				.valid(false));
+		ret.add(new ValidationTestCase<SMSConfiguration>("tooShortIdentifier")
+				.adjustment(x -> x.setIdentifier("z"))
+				.valid(false));
+		ret.add(new ValidationTestCase<SMSConfiguration>("LongToken")
+				.adjustment(x -> x.getAccount_sid())
+				.valid(false));
+		ret.add(new ValidationTestCase<SMSConfiguration>("tooLongSID")
+				.adjustment(x -> x.getAccount_sid())
+				.valid(false));
+		return ret;
+	}
+	
+	@Override
+	protected SMSConfiguration createValidTestSubject() {
+		return SMSConfiguration.create("test",
+				RandomStringUtils.randomAlphanumeric(300),
+				RandomStringUtils.randomAlphanumeric(300),
+				"ACTIVE",
+				"SMS");
+	}
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/SMSPageTest.java b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/SMSPageTest.java
new file mode 100644
index 0000000..58535bb
--- /dev/null
+++ b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/SMSPageTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.apache.fineract.cn.test.domain.ValidationTest;
+import org.apache.fineract.cn.test.domain.ValidationTestCase;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class SMSPageTest extends ValidationTest<SMSPage> {
+	
+	SMSConfiguration smsConfiguration;
+	
+	public SMSPageTest(ValidationTestCase<SMSPage> testCase) {
+		super(testCase);
+	}
+	
+	@Parameterized.Parameters
+	public static Collection testCases() {
+		final Collection<ValidationTestCase> ret = new ArrayList<>();
+		ret.add(new ValidationTestCase<SMSPage>("basicCase")
+				.adjustment(x -> {
+				})
+				.valid(true));
+		ret.add(new ValidationTestCase<SMSPage>("getSMSConfiguration")
+				.adjustment(x -> x.getSmsConfigurations())
+				.valid(true));
+		return ret;
+	}
+	
+	protected SMSPage createValidTestSubject() {
+		SMSPage smsPage = new SMSPage();
+		smsConfiguration = new SMSConfiguration();
+		SMSConfiguration.create("EmailTest",
+				"dfghjklpytredfghjkloi8u7y6trfdghjklop",
+				"ghjklp098iuyhgbnmkoiuytgtrdcfvghj",
+				"ACTIVE",
+				"SMS");
+		smsPage.setSmsConfigurations(Arrays.asList(smsConfiguration));
+		return smsPage;
+	}
+}
\ No newline at end of file
diff --git a/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/TestSuite.java b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/TestSuite.java
new file mode 100644
index 0000000..d6fcf81
--- /dev/null
+++ b/api/src/test/java/org/apache/fineract/cn/notification/api/v1/domain/TestSuite.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.api.v1.domain;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+		EmailConfigurationTest.class,
+		SMSConfigurationTest.class,
+		EmailPageTest.class,
+		EventTest.class,
+		SMSPageTest.class
+})
+public class TestSuite {
+}
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..ca2370a
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+group 'org.apache.fineract.cn.notification'
+
+task publishApiToMavenLocal {
+    dependsOn gradle.includedBuild('api').task(':publishToMavenLocal')
+}
+
+task publishServiceToMavenLocal {
+    mustRunAfter publishApiToMavenLocal
+    dependsOn gradle.includedBuild('service').task(':publishToMavenLocal')
+}
+
+task publishComponentTestToMavenLocal {
+    mustRunAfter publishApiToMavenLocal
+    mustRunAfter publishServiceToMavenLocal
+    dependsOn gradle.includedBuild('component-test').task(':publishToMavenLocal')
+}
+
+task publishToMavenLocal {
+    group 'all'
+    dependsOn publishApiToMavenLocal
+    dependsOn publishServiceToMavenLocal
+    dependsOn publishComponentTestToMavenLocal
+}
+
+task prepareForTest {
+    group 'all'
+    dependsOn publishToMavenLocal
+    dependsOn gradle.includedBuild('component-test').task(':build')
+}
+
+task licenseFormat {
+    group 'all'
+    dependsOn gradle.includedBuild('api').task(':licenseFormat')
+    dependsOn gradle.includedBuild('service').task(':licenseFormat')
+    dependsOn gradle.includedBuild('component-test').task(':licenseFormat')
+}
+
+task rat {
+    group 'all'
+    dependsOn gradle.includedBuild('api').task(':rat')
+    dependsOn gradle.includedBuild('service').task(':rat')
+    dependsOn gradle.includedBuild('component-test').task(':rat')
+}
diff --git a/component-test/build.gradle b/component-test/build.gradle
new file mode 100644
index 0000000..2e29cf4
--- /dev/null
+++ b/component-test/build.gradle
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+buildscript {
+    ext {
+        springBootVersion = '1.4.1.RELEASE'
+    }
+
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+    }
+}
+
+plugins {
+    id "com.github.hierynomus.license" version "0.13.1"
+    id("org.nosphere.apache.rat") version "0.3.1"
+}
+apply from: '../shared.gradle'
+
+dependencies {
+    compile(
+            [group: 'org.apache.fineract.cn.notification', name: 'api', version: project.version],
+            [group: 'org.apache.fineract.cn.notification', name: 'service', version: project.version],
+            [group: 'org.apache.fineract.cn.anubis', name: 'test', version: versions.frameworkanubis],
+            [group: 'org.apache.fineract.cn', name: 'api', version: versions.frameworkapi],
+            [group: 'org.apache.fineract.cn', name: 'test', version: versions.frameworktest],
+            [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-test'],
+    )
+}
+
+publishing {
+    publications {
+        mavenJava(MavenPublication) {
+            from components.java
+        }
+    }
+}
diff --git a/component-test/settings.gradle b/component-test/settings.gradle
new file mode 100644
index 0000000..a07a3bc
--- /dev/null
+++ b/component-test/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+rootProject.name = 'component-test'
\ No newline at end of file
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/SuiteTestEnvironment.java b/component-test/src/main/java/org/apache/fineract/cn/notification/SuiteTestEnvironment.java
new file mode 100644
index 0000000..5063d2e
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/SuiteTestEnvironment.java
@@ -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.
+ */
+package org.apache.fineract.cn.notification;
+
+import org.apache.fineract.cn.test.env.TestEnvironment;
+import org.apache.fineract.cn.test.fixture.cassandra.CassandraInitializer;
+import org.apache.fineract.cn.test.fixture.mariadb.MariaDBInitializer;
+import org.junit.ClassRule;
+import org.junit.rules.RuleChain;
+import org.junit.rules.RunExternalResourceOnce;
+import org.junit.rules.TestRule;
+
+/**
+ * This contains the database resources required by the test.  They are in a separate
+ * class so that the test suite can initialize them before the classes it calls. This
+ * makes test runs faster and prevents tests from "stepping on each other's toes" when
+ * initializing and de-initializing external resources.
+ */
+public class SuiteTestEnvironment {
+	static final String APP_VERSION = "1";
+	static final String APP_NAME = "notification-v" + APP_VERSION;
+	
+	static final TestEnvironment testEnvironment = new TestEnvironment(APP_NAME);
+	static final CassandraInitializer cassandraInitializer = new CassandraInitializer();
+	static final MariaDBInitializer mariaDBInitializer = new MariaDBInitializer();
+	
+	@ClassRule
+	public static TestRule orderClassRules = RuleChain
+			.outerRule(new RunExternalResourceOnce(testEnvironment))
+			.around(new RunExternalResourceOnce(cassandraInitializer))
+			.around(new RunExternalResourceOnce(mariaDBInitializer));
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/TestEmailService.java b/component-test/src/main/java/org/apache/fineract/cn/notification/TestEmailService.java
new file mode 100644
index 0000000..6bf89bc
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/TestEmailService.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.cn.notification;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.api.util.NotFoundException;
+import org.apache.fineract.cn.customer.api.v1.client.CustomerNotFoundException;
+import org.apache.fineract.cn.notification.api.v1.client.ConfigurationNotFoundException;
+import org.apache.fineract.cn.notification.api.v1.client.NotificationManager;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.internal.service.NotificationService;
+import org.apache.fineract.cn.notification.util.DomainObjectGenerator;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class TestEmailService extends TestNotification {
+	
+	private final String configIdentifier = "Gmail";
+	@Autowired
+	private NotificationService notificationService;
+	@Autowired
+	private NotificationManager notificationManager;
+	@Autowired
+	private EventRecorder eventRecorder;
+	
+	public TestEmailService() {
+		super();
+	}
+	
+	@Test
+	public void sendEmail() {
+		this.logger.info("Send Email Notification");
+		this.notificationService.sendEmail("fineractcnnotificationdemo@gmail.com ",
+				"egraham15@alustudent.com",
+				"Talk is cheap, show me the code",
+				"Dear Valued Customer,\n\nComponent test sample message\n\nBest Regards\nYour MFI");
+	}
+	
+	@Test
+	public void shouldRetrieveEmailConfigurationEntity() {
+		logger.info("Create and retrieve Email Gateway configuration");
+		EmailConfiguration sampleRetrieved = this.notificationManager.findEmailConfigurationByIdentifier(configIdentifier);
+		Assert.assertNotNull(sampleRetrieved);
+		Assert.assertEquals(sampleRetrieved.getIdentifier(), configIdentifier);
+	}
+	
+	@Test
+	public void shouldCreateNewEmailConfigurationEntity() throws InterruptedException{
+		logger.info("Create Email Gateway configuration");
+		this.notificationManager.createEmailConfiguration(DomainObjectGenerator.emailConfiguration());
+		
+		eventRecorder.wait(NotificationEventConstants.POST_EMAIL_CONFIGURATION,EmailConfiguration.class);
+	}
+	
+	@Test(expected = NotFoundException.class)
+	public void emailConfigurationNotFound() throws CustomerNotFoundException {
+		logger.info("Configuration not found");
+		try {
+			this.notificationManager.findEmailConfigurationByIdentifier(RandomStringUtils.randomAlphanumeric(8));
+		} catch (final ConfigurationNotFoundException ex) {
+			logger.info("Error Asserted");
+		}
+	}
+	
+	@Test
+	public void checkEmailConfigurationEntityExist() {
+		logger.info("Email Gateway configuration Exist");
+		Assert.assertTrue(this.notificationService.emailConfigurationExists(configIdentifier));
+	}
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/TestNotification.java b/component-test/src/main/java/org/apache/fineract/cn/notification/TestNotification.java
new file mode 100644
index 0000000..6a6bf6b
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/TestNotification.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.cn.notification;
+
+import org.apache.fineract.cn.anubis.test.v1.TenantApplicationSecurityEnvironmentTestRule;
+import org.apache.fineract.cn.api.context.AutoUserContext;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.NotificationConfiguration;
+import org.apache.fineract.cn.test.fixture.TenantDataStoreContextTestRule;
+import org.apache.fineract.cn.test.listener.EnableEventRecording;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+import org.springframework.cloud.netflix.ribbon.RibbonClient;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.security.interfaces.RSAPrivateKey;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
+		classes = {TestNotification.TestConfiguration.class})
+public class TestNotification extends SuiteTestEnvironment {
+	
+	@ClassRule
+	public final static TenantDataStoreContextTestRule tenantDataStoreContext = TenantDataStoreContextTestRule.forRandomTenantName(cassandraInitializer, mariaDBInitializer);
+	private static final String LOGGER_NAME = "test-logger";
+	private static final String TEST_USER = "homer";
+	@SuppressWarnings("WeakerAccess")
+	@Autowired
+	@Qualifier(LOGGER_NAME)
+	Logger logger;
+	private AutoUserContext userContext;
+	@Autowired
+	private EventRecorder eventRecorder;
+	@Rule
+	public final TenantApplicationSecurityEnvironmentTestRule tenantApplicationSecurityEnvironment
+			= new TenantApplicationSecurityEnvironmentTestRule(testEnvironment, this::waitForInitialize);
+	
+	public TestNotification() {
+		super();
+	}
+	
+	@Before
+	public void prepTest() {
+		userContext = tenantApplicationSecurityEnvironment.createAutoUserContext(TestNotification.TEST_USER);
+		final RSAPrivateKey tenantPrivateKey = tenantApplicationSecurityEnvironment.getSystemSecurityEnvironment().tenantPrivateKey();
+		logger.info("tenantPrivateKey = {}", tenantPrivateKey);
+	}
+	
+	@After
+	public void cleanTest() {
+		userContext.close();
+		eventRecorder.clear();
+	}
+	
+	public boolean waitForInitialize() {
+		try {
+			return this.eventRecorder.wait(NotificationEventConstants.INITIALIZE, APP_VERSION);
+		} catch (final InterruptedException e) {
+			throw new IllegalStateException(e);
+		}
+	}
+	
+	@Configuration
+	@EnableEventRecording
+	@EnableFeignClients(basePackages = {"org.apache.fineract.cn.notification.api.v1.client"})
+	@RibbonClient(name = APP_NAME)
+	@ComponentScan({"org.apache.fineract.cn.notification.listener",
+			"org.apache.fineract.cn.notification.service.internal.service",
+			"org.apache.fineract.cn.notification.service.internal.service.helperservice"
+	})
+	@Import({NotificationConfiguration.class})
+	public static class TestConfiguration {
+		public TestConfiguration() {
+			super();
+		}
+		
+		@Bean(name = LOGGER_NAME)
+		public Logger logger() {
+			return LoggerFactory.getLogger(LOGGER_NAME);
+		}
+	}
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/TestSMSService.java b/component-test/src/main/java/org/apache/fineract/cn/notification/TestSMSService.java
new file mode 100644
index 0000000..8ce0512
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/TestSMSService.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.fineract.cn.api.util.NotFoundException;
+import org.apache.fineract.cn.customer.api.v1.client.CustomerNotFoundException;
+import org.apache.fineract.cn.notification.api.v1.client.ConfigurationNotFoundException;
+import org.apache.fineract.cn.notification.api.v1.client.NotificationManager;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.internal.service.NotificationService;
+import org.apache.fineract.cn.notification.util.DomainObjectGenerator;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class TestSMSService extends TestNotification {
+	
+	@Autowired
+	private NotificationService notificationService;
+	
+	@Autowired
+	private NotificationManager notificationManager;
+	
+	@Autowired
+	private EventRecorder eventRecorder;
+	
+	private String configIdentifier = "Twilio";
+	
+	public TestSMSService() {
+		super();
+	}
+	
+	
+	@Test
+	public void shouldCreateNewSMSConfigurationEntity() throws InterruptedException{
+		logger.info("Create SMS Gateway configuration");
+		this.notificationManager.createSMSConfiguration(DomainObjectGenerator.smsConfiguration());
+		
+		eventRecorder.wait(NotificationEventConstants.POST_EMAIL_CONFIGURATION, SMSConfiguration.class);
+	}
+	
+	@Test
+	public void shouldTriggerCustomerCreated() throws InterruptedException{
+		logger.info("Create SMS Gateway configuration");
+		
+		eventRecorder.wait(NotificationEventConstants.POST_EMAIL_CONFIGURATION, SMSConfiguration.class);
+	}
+	
+	@Test(expected = NotFoundException.class)
+	public void smsConfigurationNotFound() throws CustomerNotFoundException {
+		logger.info("SMS Gateway configuration Not Found");
+		try {
+			this.notificationManager.findSMSConfigurationByIdentifier(RandomStringUtils.randomAlphanumeric(8));
+		} catch (final ConfigurationNotFoundException ex) {
+			logger.info("Error Asserted");
+		}
+	}
+	@Test
+	public void sendSMS() {
+		this.logger.info("Send SMS Notification");
+//		this.notificationService.sendSMS("+23058409206",
+//				"Dear Valued Customer\n\nTalk is cheap show me the code\n\nBest Regards\nYour MFI");
+	}
+	
+	@Test
+	public void shouldCreateAndRetrieveSMSConfigurationEntity() {
+		logger.info("Create and Retrieve SMS Gateway configuration");
+		final SMSConfiguration smsConfiguration = DomainObjectGenerator.smsConfiguration();
+		this.notificationManager.createSMSConfiguration(smsConfiguration);
+		
+		SMSConfiguration sampleRetrieved = this.notificationManager.findSMSConfigurationByIdentifier(configIdentifier);
+		Assert.assertNotNull(sampleRetrieved);
+		Assert.assertEquals(sampleRetrieved.getIdentifier(), configIdentifier);
+	}
+	
+	@Test
+	public void checkSMSConfigurationEntityExist() {
+		logger.info("SMS Gateway configuration Exist");
+		Assert.assertTrue(this.notificationService.smsConfigurationExists(configIdentifier));
+	}
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/TestSuite.java b/component-test/src/main/java/org/apache/fineract/cn/notification/TestSuite.java
new file mode 100644
index 0000000..868e949
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/TestSuite.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+		TestEmailService.class,
+		TestSMSService.class,
+})
+public class TestSuite extends SuiteTestEnvironment {
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/listener/MigrationEventListener.java b/component-test/src/main/java/org/apache/fineract/cn/notification/listener/MigrationEventListener.java
new file mode 100644
index 0000000..38e2c8d
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/listener/MigrationEventListener.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.cn.notification.listener;
+
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class MigrationEventListener {
+	
+	private final EventRecorder eventRecorder;
+	
+	@Autowired
+	public MigrationEventListener(@SuppressWarnings("SpringJavaAutowiringInspection") final EventRecorder eventRecorder) {
+		super();
+		this.eventRecorder = eventRecorder;
+	}
+	
+	@JmsListener(
+			subscription = NotificationEventConstants.DESTINATION,
+			destination = NotificationEventConstants.DESTINATION,
+			selector = NotificationEventConstants.SELECTOR_INITIALIZE
+	)
+	public void onInitialization(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                             final String payload) {
+		this.eventRecorder.event(tenant, NotificationEventConstants.INITIALIZE, payload, String.class);
+	}
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/listener/NotificationEventListener.java b/component-test/src/main/java/org/apache/fineract/cn/notification/listener/NotificationEventListener.java
new file mode 100644
index 0000000..838b2c7
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/listener/NotificationEventListener.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.listener;
+
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.test.listener.EventRecorder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+@SuppressWarnings("unused")
+@Component
+public class NotificationEventListener {
+	
+	private final EventRecorder eventRecorder;
+	
+	@Autowired
+	public NotificationEventListener(@SuppressWarnings("SpringJavaAutowiringInspection") final EventRecorder eventRecorder) {
+		super();
+		this.eventRecorder = eventRecorder;
+	}
+	
+	@JmsListener(
+			subscription = NotificationEventConstants.DESTINATION,
+			destination = NotificationEventConstants.DESTINATION,
+			selector = NotificationEventConstants.SELECTOR_POST_SMS_NOTIFICATION
+	)
+	public void onPostSMS(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                      final String payload) {
+		this.eventRecorder.event(tenant, NotificationEventConstants.POST_SMS_NOTIFICATION, payload, String.class);
+	}
+	
+	@JmsListener(
+			subscription = NotificationEventConstants.DESTINATION,
+			destination = NotificationEventConstants.DESTINATION,
+			selector = NotificationEventConstants.SELECTOR_POST_SMS_CONFIGURATION
+	)
+	public void onCreateSMSConfiguration(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                     final String payload) {
+		this.eventRecorder.event(tenant, NotificationEventConstants.POST_SMS_NOTIFICATION, payload, String.class);
+	}
+}
diff --git a/component-test/src/main/java/org/apache/fineract/cn/notification/util/DomainObjectGenerator.java b/component-test/src/main/java/org/apache/fineract/cn/notification/util/DomainObjectGenerator.java
new file mode 100644
index 0000000..d323eea
--- /dev/null
+++ b/component-test/src/main/java/org/apache/fineract/cn/notification/util/DomainObjectGenerator.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.cn.notification.util;
+/*
+ebenezergraham created on 8/20/18
+*/
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+
+public class DomainObjectGenerator {
+	
+	public static EmailConfiguration emailConfiguration() {
+		EmailConfiguration emailConfiguration = EmailConfiguration.create("emailtest",
+				"smtp.google.com",
+				"1233",
+				"smtp",
+				"example",
+				RandomStringUtils.randomAlphanumeric(16),
+				"true",
+				"true",
+				"ACTIVE");
+		return emailConfiguration;
+	}
+	
+	public static SMSConfiguration smsConfiguration() {
+		SMSConfiguration smsConfiguration = SMSConfiguration.create(
+				RandomStringUtils.randomAlphanumeric(8),
+				RandomStringUtils.randomAlphanumeric(16),
+				RandomStringUtils.randomAlphanumeric(16),
+				"+309483932",
+				"ACTIVE");
+		
+		return smsConfiguration;
+	}
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..400f155
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..c563c1a
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri May 18 16:18:58 MUT 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4453cce
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/service/build.gradle b/service/build.gradle
new file mode 100644
index 0000000..cb2d88c
--- /dev/null
+++ b/service/build.gradle
@@ -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.
+ */
+
+buildscript {
+    ext {
+        springBootVersion = '1.4.1.RELEASE'
+    }
+
+    repositories {
+        jcenter()
+    }
+
+    dependencies {
+        classpath ("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
+    }
+}
+
+plugins {
+    id "com.github.hierynomus.license" version "0.13.1"
+    id("org.nosphere.apache.rat") version "0.3.1"
+}
+
+apply from: '../shared.gradle'
+
+apply plugin: 'spring-boot'
+
+springBoot {
+    executable = true
+    classifier = 'boot'
+}
+
+dependencies {
+    compile(
+            [group: 'com.twilio.sdk', name: 'twilio', version: versions.twilioapi],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-mail', version: versions.springjavamail],
+
+            [group: 'org.apache.fineract.cn.customer', name: 'api', version: versions.fineractcncustomer],
+            [group: 'org.apache.fineract.cn.portfolio', name: 'api', version: versions.fineractcnportfolio],
+            [group: 'org.apache.fineract.cn.office', name: 'api', version: versions.fineractcnoffice],
+            [group: 'org.apache.fineract.cn.identity', name: 'api', version: versions.fineractcnidentity],
+
+            [group: 'org.springframework.cloud', name: 'spring-cloud-starter-config'],
+            [group: 'org.springframework.cloud', name: 'spring-cloud-starter-eureka'],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-jetty'],
+            [group: 'org.apache.fineract.cn.notification', name: 'api', version: project.version],
+            [group: 'org.apache.fineract.cn.anubis', name: 'library', version: versions.frameworkanubis],
+            [group: 'com.google.code.gson', name: 'gson'],
+            [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
+            [group: 'org.apache.fineract.cn', name: 'async', version: versions.frameworkasync],
+            [group: 'org.apache.fineract.cn', name: 'cassandra', version: versions.frameworkcassandra],
+            [group: 'org.apache.fineract.cn', name: 'mariadb', version: versions.frameworkmariadb],
+            [group: 'org.apache.fineract.cn', name: 'command', version: versions.frameworkcommand],
+            [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator]
+    )
+}
+
+publishToMavenLocal.dependsOn bootRepackage
+
+publishing {
+    publications {
+        service(MavenPublication) {
+            from components.java
+            groupId project.group
+            artifactId project.name
+            version project.version
+        }
+        bootService(MavenPublication) {
+            // "boot" jar
+            artifact ("$buildDir/libs/$project.name-$version-boot.jar")
+            groupId project.group
+            artifactId ("$project.name-boot")
+            version project.version
+        }
+    }
+}
diff --git a/service/out/production/resources/application.yml b/service/out/production/resources/application.yml
new file mode 100644
index 0000000..fa7165e
--- /dev/null
+++ b/service/out/production/resources/application.yml
@@ -0,0 +1,88 @@
+#
+# 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.
+#
+
+spring:
+  cloud:
+    discovery:
+      enabled: false
+    config:
+      enabled: false
+    mail:
+      host: smtp.gmail.com
+      port: 587
+      username:
+      password:
+      properties:
+        debug: true
+        mail:
+          smtp:
+            auth: true
+            starttls:
+              enable: true
+
+
+
+eureka:
+  client:
+    serviceUrl:
+      defaultZone: http://localhost:8761/eureka/
+
+server:
+  port: 8081
+  contextPath: /notification/v1/*
+
+cassandra:
+  clusterName: staging_cluster
+  contactPoints: 127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042
+  keyspace: seshat
+  cl:
+    read: LOCAL_QUORUM
+    write: LOCAL_QUORUM
+    delete: LOCAL_QUORUM
+
+mariadb:
+  driverClass: org.mariadb.jdbc.Driver
+  database: seshat
+  host: localhost
+  port: 3306
+  user: root
+  password: mysql
+
+bonecp:
+  idleMaxAgeInMinutes: 240
+  idleConnectionTestPeriodInMinutes: 60
+  maxConnectionsPerPartition: 10
+  minConnectionsPerPartition: 1
+  partitionCount: 2
+  acquireIncrement: 5
+  statementsCacheSize: 100
+
+async:
+  corePoolSize: 32
+  maxPoolSize: 16384
+  queueCapacity: 0
+  threadName: async-processor-
+
+flyway:
+  enabled: false
+
+smssender:
+  accountSID: AC1fde2c6f26f367b93231c5fdb944c908
+  authToken: bc9a53e41745b8471e0ecafc859d86aa
+  senderNumber: +1 510-944-1898
diff --git a/service/out/production/resources/bootstrap.yml b/service/out/production/resources/bootstrap.yml
new file mode 100644
index 0000000..76c2441
--- /dev/null
+++ b/service/out/production/resources/bootstrap.yml
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+spring:
+    application:
+        name: notification-v1
diff --git a/service/out/production/resources/db/migrations/mariadb/V1__initial_setup.sql b/service/out/production/resources/db/migrations/mariadb/V1__initial_setup.sql
new file mode 100644
index 0000000..57cefe1
--- /dev/null
+++ b/service/out/production/resources/db/migrations/mariadb/V1__initial_setup.sql
@@ -0,0 +1,56 @@
+--
+-- 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.
+--
+
+-- -----------------------------------------------------
+-- Table wada_sms_gateway_configurations
+-- -----------------------------------------------------
+CREATE TABLE wada_sms_gateway_configurations (
+  id INT(11) NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(45) NULL DEFAULT NULL,
+  account_sid VARCHAR(255) NOT NULL,
+  auth_token VARCHAR(255) NOT NULL,
+  sender_number VARCHAR(45) NOT NULL,
+  state VARCHAR(45) NULL DEFAULT NULL,
+  PRIMARY KEY (id));
+
+-- -----------------------------------------------------
+-- Table wada_email_gateway_configurations
+-- -----------------------------------------------------
+CREATE TABLE wada_email_gateway_configurations (
+  id INT(11) NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(45) NULL DEFAULT NULL,
+  host VARCHAR(45) NOT NULL,
+  port VARCHAR(45) NOT NULL,
+  username VARCHAR(45) NOT NULL,
+  app_password VARCHAR(255) NOT NULL,
+  protocol VARCHAR(45)NOT NULL,
+  smtp_auth VARCHAR (45)NOT NULL,
+  start_tls VARCHAR (45)NOT NULL,
+  state VARCHAR(45)NOT NULL,
+  PRIMARY KEY (id));
+
+-- -----------------------------------------------------
+-- Table wada_templates
+-- -----------------------------------------------------
+CREATE TABLE wada_templates (
+  id INT(11) NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(45) NULL DEFAULT NULL,
+  event VARCHAR(45) NULL DEFAULT NULL,
+  url VARCHAR(255) NOT NULL,
+  PRIMARY KEY (id));
diff --git a/service/out/production/resources/db/migrations/mariadb/V2__sms_gateway_configurations.sql b/service/out/production/resources/db/migrations/mariadb/V2__sms_gateway_configurations.sql
new file mode 100644
index 0000000..d795f01
--- /dev/null
+++ b/service/out/production/resources/db/migrations/mariadb/V2__sms_gateway_configurations.sql
@@ -0,0 +1,20 @@
+--
+-- 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.
+--
+
+INSERT INTO wada_sms_gateway_configurations VALUES ('1', 'Twilio', 'AC1fde2c6f26f367b93231c5fdb944c908', 'c9a53e41745b8471e0ecafc859d86aa', '+1 510-944-1898', 'ACTIVE');
\ No newline at end of file
diff --git a/service/out/production/resources/db/migrations/mariadb/V3__email_gateway_configurations.sql b/service/out/production/resources/db/migrations/mariadb/V3__email_gateway_configurations.sql
new file mode 100644
index 0000000..9482b7c
--- /dev/null
+++ b/service/out/production/resources/db/migrations/mariadb/V3__email_gateway_configurations.sql
@@ -0,0 +1,20 @@
+--
+-- 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.
+--
+
+INSERT INTO wada_email_gateway_configurations VALUES ('1', 'Gmail', 'smtp.gmail.com', '587','fineractcnnotificationdemo@gmail.com', 'pnuugpwmcibipdpw', 'smtp', 'true', 'true', 'ACTIVE');
\ No newline at end of file
diff --git a/service/out/production/resources/logback.xml b/service/out/production/resources/logback.xml
new file mode 100644
index 0000000..5cd9b4c
--- /dev/null
+++ b/service/out/production/resources/logback.xml
@@ -0,0 +1,58 @@
+<!--
+
+    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.
+
+-->
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/notification.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>logs/archive/notification.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>
+            <totalSizeCap>2GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="io" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="net" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <root level="DEBUG">
+        <appender-ref ref="FILE"/>
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/service/settings.gradle b/service/settings.gradle
new file mode 100644
index 0000000..1a4c2fd
--- /dev/null
+++ b/service/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+rootProject.name = 'service'
\ No newline at end of file
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/NotificationApplication.java b/service/src/main/java/org/apache/fineract/cn/notification/service/NotificationApplication.java
new file mode 100644
index 0000000..29d448b
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/NotificationApplication.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service;
+
+import org.springframework.boot.SpringApplication;
+
+public class NotificationApplication {
+	
+	public NotificationApplication() {
+		super();
+	}
+	
+	public static void main(String[] args) {
+		SpringApplication.run(NotificationConfiguration.class, args);
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/NotificationConfiguration.java b/service/src/main/java/org/apache/fineract/cn/notification/service/NotificationConfiguration.java
new file mode 100644
index 0000000..4f9a63c
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/NotificationConfiguration.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service;
+
+import org.apache.activemq.command.ActiveMQTopic;
+import org.apache.activemq.jms.pool.PooledConnectionFactory;
+import org.apache.activemq.spring.ActiveMQConnectionFactory;
+import org.apache.fineract.cn.identity.api.v1.client.IdentityManager;
+import org.apache.fineract.cn.anubis.config.EnableAnubis;
+import org.apache.fineract.cn.async.config.EnableAsync;
+import org.apache.fineract.cn.cassandra.config.EnableCassandra;
+import org.apache.fineract.cn.command.config.EnableCommandProcessing;
+import org.apache.fineract.cn.customer.api.v1.client.CustomerManager;
+import org.apache.fineract.cn.lang.ApplicationName;
+import org.apache.fineract.cn.lang.config.EnableServiceException;
+import org.apache.fineract.cn.lang.config.EnableTenantContext;
+import org.apache.fineract.cn.mariadb.config.EnableMariaDB;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.jms.annotation.EnableJms;
+import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
+import org.springframework.jms.config.JmsListenerContainerFactory;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+@SuppressWarnings("WeakerAccess")
+@Configuration
+@EnableAutoConfiguration
+@EnableDiscoveryClient
+@EnableAsync
+@EnableTenantContext
+@EnableCassandra
+@EnableMariaDB
+@EnableCommandProcessing
+@EnableAnubis
+@EnableServiceException
+@EnableJms
+@EnableFeignClients(
+		clients = {
+				CustomerManager.class,
+				IdentityManager.class
+		}
+)
+@ComponentScan({
+		"org.apache.fineract.cn.notification.service.rest",
+		"org.apache.fineract.cn.notification.service.listener",
+		"org.apache.fineract.cn.notification.service.internal.service",
+		"org.apache.fineract.cn.notification.service.internal.repository",
+		"org.apache.fineract.cn.notification.service.internal.command.handler",
+}
+)
+@EnableJpaRepositories({
+		"org.apache.fineract.cn.notification.service.internal.repository"
+})
+@EntityScan(basePackages = "org.apache.fineract.cn.notification.service.internal.repository")
+public class NotificationConfiguration extends WebMvcConfigurerAdapter {
+	
+	private final Environment environment;
+	
+	public NotificationConfiguration(Environment environment) {
+		super();
+		this.environment = environment;
+	}
+	
+	
+	@Override
+	public void configurePathMatch(final PathMatchConfigurer configurer) {
+		configurer.setUseSuffixPatternMatch(Boolean.FALSE);
+	}
+	
+	@Bean
+	public PooledConnectionFactory jmsFactory() {
+		PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory();
+		ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
+		activeMQConnectionFactory.setBrokerURL(this.environment.getProperty("activemq.brokerUrl", "vm://localhost?broker.persistent=falseac"));
+		pooledConnectionFactory.setConnectionFactory(activeMQConnectionFactory);
+		return pooledConnectionFactory;
+	}
+	
+	@Bean
+	public JmsListenerContainerFactory jmsListenerContainerFactory(PooledConnectionFactory jmsFactory) {
+		DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
+		factory.setPubSubDomain(true);
+		factory.setConnectionFactory(jmsFactory);
+		factory.setErrorHandler(ex -> {
+			loggerBean().error(ex.getCause().toString());
+		});
+		factory.setConcurrency(this.environment.getProperty("activemq.concurrency", "1-1"));
+		return factory;
+	}
+	
+	@Bean
+	public JmsTemplate jmsTemplate(ApplicationName applicationName, PooledConnectionFactory jmsFactory) {
+		ActiveMQTopic activeMQTopic = new ActiveMQTopic(applicationName.toString());
+		JmsTemplate jmsTemplate = new JmsTemplate();
+		jmsTemplate.setPubSubDomain(true);
+		jmsTemplate.setConnectionFactory(jmsFactory);
+		jmsTemplate.setDefaultDestination(activeMQTopic);
+		return jmsTemplate;
+	}
+	
+	@Bean(
+			name = {ServiceConstants.LOGGER_NAME}
+	)
+	public Logger loggerBean() {
+		return LoggerFactory.getLogger(ServiceConstants.LOGGER_NAME);
+	}
+	
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/ServiceConstants.java b/service/src/main/java/org/apache/fineract/cn/notification/service/ServiceConstants.java
new file mode 100644
index 0000000..dc96c42
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/ServiceConstants.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service;
+
+public interface ServiceConstants {
+	String LOGGER_NAME = "notification-logger";
+	
+	String MAIL_TRANSPORT_PROTOCOL_PROPERTY = "mail.transport.protocol";
+	String MAIL_TRANSPORT_PROTOCOL_VALUE = "smtp";
+	String MAIL_SMTP_AUTH_PROPERTY = "mail.smtp.auth";
+	String MAIL_SMTP_AUTH_VALUE = "true";
+	String MAIL_SMTP_STARTTLS_ENABLE_PROPERTY = "mail.smtp.starttls.enable";
+	String MAIL_SMTP_STARTTLS_ENABLE_VALUE = "true";
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/CreateEmailConfigurationCommand.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/CreateEmailConfigurationCommand.java
new file mode 100644
index 0000000..828ba4e
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/CreateEmailConfigurationCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command;
+
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+
+public class CreateEmailConfigurationCommand {
+	
+	private final EmailConfiguration emailConfiguration;
+	
+	public CreateEmailConfigurationCommand(final EmailConfiguration emailConfiguration) {
+		super();
+		this.emailConfiguration = emailConfiguration;
+	}
+	
+	public EmailConfiguration getEmailConfiguration() {
+		return this.emailConfiguration;
+	}
+	
+	@Override
+	public String toString() {
+		return "CreateEmailConfigurationCommand{"
+				+ "EmailConfiguration=" + emailConfiguration.getIdentifier()
+				+ '}';
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/CreateSMSConfigurationCommand.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/CreateSMSConfigurationCommand.java
new file mode 100644
index 0000000..ef206c8
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/CreateSMSConfigurationCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command;
+
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+
+public class CreateSMSConfigurationCommand {
+	
+	private final SMSConfiguration smsConfiguration;
+	
+	public CreateSMSConfigurationCommand(final SMSConfiguration smsConfiguration) {
+		super();
+		this.smsConfiguration = smsConfiguration;
+	}
+	
+	public SMSConfiguration getSMSConfiguration() {
+		return this.smsConfiguration;
+	}
+	
+	@Override
+	public String toString() {
+		return "CreateSMSConfigurationCommand{"
+				+ "SMSConfiguration=" + smsConfiguration.getIdentifier()
+				+ '}';
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/InitializeServiceCommand.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/InitializeServiceCommand.java
new file mode 100644
index 0000000..9ab4d6f
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/InitializeServiceCommand.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command;
+
+public class InitializeServiceCommand {
+	
+	public InitializeServiceCommand() {
+		super();
+	}
+	
+	@Override
+	public String toString() {
+		return "InitializeServiceCommand{}";
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/PostSMSCommand.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/PostSMSCommand.java
new file mode 100644
index 0000000..2ffc416
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/PostSMSCommand.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command;
+
+public class PostSMSCommand {
+	
+	private final String identifier;
+	
+	public PostSMSCommand(final String identifier) {
+		super();
+		this.identifier = identifier;
+	}
+	
+	public String getIdentifier() {
+		return this.identifier;
+	}
+	
+	@Override
+	public String toString() {
+		return "PostSMSCommand{"
+				+ "PostSMS=" + identifier
+				+ '}';
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/EmailConfigurationAggregate.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/EmailConfigurationAggregate.java
new file mode 100644
index 0000000..6cc80d0
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/EmailConfigurationAggregate.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command.handler;
+
+import org.apache.fineract.cn.command.annotation.Aggregate;
+import org.apache.fineract.cn.command.annotation.CommandHandler;
+import org.apache.fineract.cn.command.annotation.CommandLogLevel;
+import org.apache.fineract.cn.command.annotation.EventEmitter;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.internal.command.CreateEmailConfigurationCommand;
+import org.apache.fineract.cn.notification.service.internal.mapper.EmailConfigurationMapper;
+import org.apache.fineract.cn.notification.service.internal.repository.EmailGatewayConfigurationEntity;
+import org.apache.fineract.cn.notification.service.internal.repository.EmailGatewayConfigurationRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@SuppressWarnings("unused")
+@Aggregate
+public class EmailConfigurationAggregate {
+	
+	private final EmailGatewayConfigurationRepository emailGatewayConfigurationRepository;
+	
+	@Autowired
+	public EmailConfigurationAggregate(EmailGatewayConfigurationRepository emailGatewayConfigurationRepository) {
+		super();
+		this.emailGatewayConfigurationRepository = emailGatewayConfigurationRepository;
+	}
+	
+	@CommandHandler(logStart = CommandLogLevel.DEBUG, logFinish = CommandLogLevel.DEBUG)
+	@Transactional
+	@EventEmitter(selectorName = NotificationEventConstants.SELECTOR_NAME, selectorValue = NotificationEventConstants.POST_EMAIL_CONFIGURATION)
+	public String createEmailConfiguration(final CreateEmailConfigurationCommand createEmailConfigurationCommand) {
+		
+		EmailConfiguration emailConfiguration = createEmailConfigurationCommand.getEmailConfiguration();
+		final EmailGatewayConfigurationEntity entity = EmailConfigurationMapper.map(emailConfiguration);
+		this.emailGatewayConfigurationRepository.save(entity);
+		
+		return emailConfiguration.getIdentifier();
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/EventsAggregate.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/EventsAggregate.java
new file mode 100644
index 0000000..27f129b
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/EventsAggregate.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command.handler;
+
+import org.apache.fineract.cn.command.annotation.Aggregate;
+import org.apache.fineract.cn.command.annotation.CommandHandler;
+import org.apache.fineract.cn.command.annotation.CommandLogLevel;
+import org.apache.fineract.cn.command.annotation.EventEmitter;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.internal.command.CreateSMSConfigurationCommand;
+import org.apache.fineract.cn.notification.service.internal.command.PostSMSCommand;
+import org.apache.fineract.cn.notification.service.internal.mapper.SMSConfigurationMapper;
+import org.apache.fineract.cn.notification.service.internal.repository.SMSGatewayConfigurationEntity;
+import org.apache.fineract.cn.notification.service.internal.repository.SMSGatewayConfigurationRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@SuppressWarnings("unused")
+@Aggregate
+public class EventsAggregate {
+	
+	public EventsAggregate() {
+		super();
+	}
+	
+	@CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
+	@Transactional
+	@EventEmitter(selectorName = NotificationEventConstants.SELECTOR_NAME, selectorValue = NotificationEventConstants.POST_SMS_NOTIFICATION)
+	public String postSMS(final PostSMSCommand postSMSCommand) {
+		return postSMSCommand.getIdentifier();
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/MigrationAggregate.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/MigrationAggregate.java
new file mode 100644
index 0000000..1abc754
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/MigrationAggregate.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command.handler;
+
+import org.apache.fineract.cn.command.annotation.Aggregate;
+import org.apache.fineract.cn.command.annotation.CommandHandler;
+import org.apache.fineract.cn.command.annotation.CommandLogLevel;
+import org.apache.fineract.cn.command.annotation.EventEmitter;
+import org.apache.fineract.cn.lang.ApplicationName;
+import org.apache.fineract.cn.mariadb.domain.FlywayFactoryBean;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.apache.fineract.cn.notification.service.internal.command.InitializeServiceCommand;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.sql.DataSource;
+
+@SuppressWarnings({
+		"unused"
+})
+@Aggregate
+public class MigrationAggregate {
+	
+	private final Logger logger;
+	private final DataSource dataSource;
+	private final FlywayFactoryBean flywayFactoryBean;
+	private final ApplicationName applicationName;
+	
+	@Autowired
+	public MigrationAggregate(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+	                          final DataSource dataSource,
+	                          final FlywayFactoryBean flywayFactoryBean,
+	                          final ApplicationName applicationName) {
+		super();
+		this.logger = logger;
+		this.dataSource = dataSource;
+		this.flywayFactoryBean = flywayFactoryBean;
+		this.applicationName = applicationName;
+	}
+	
+	@CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
+	@Transactional
+	@EventEmitter(selectorName = NotificationEventConstants.SELECTOR_NAME, selectorValue = NotificationEventConstants.INITIALIZE)
+	public String initialize(final InitializeServiceCommand initializeServiceCommand) {
+		this.logger.debug("Start service migration.");
+		this.flywayFactoryBean.create(this.dataSource).migrate();
+		return this.applicationName.getVersionString();
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/SMSConfigurationAggregate.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/SMSConfigurationAggregate.java
new file mode 100644
index 0000000..1d240fb
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/command/handler/SMSConfigurationAggregate.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.command.handler;
+
+import org.apache.fineract.cn.command.annotation.Aggregate;
+import org.apache.fineract.cn.command.annotation.CommandHandler;
+import org.apache.fineract.cn.command.annotation.CommandLogLevel;
+import org.apache.fineract.cn.command.annotation.EventEmitter;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.apache.fineract.cn.notification.api.v1.events.NotificationEventConstants;
+import org.apache.fineract.cn.notification.service.internal.command.CreateSMSConfigurationCommand;
+import org.apache.fineract.cn.notification.service.internal.mapper.SMSConfigurationMapper;
+import org.apache.fineract.cn.notification.service.internal.repository.SMSGatewayConfigurationEntity;
+import org.apache.fineract.cn.notification.service.internal.repository.SMSGatewayConfigurationRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@SuppressWarnings("unused")
+@Aggregate
+public class SMSConfigurationAggregate {
+	
+	private final SMSGatewayConfigurationRepository smsGatewayConfigurationRepository;
+	
+	@Autowired
+	public SMSConfigurationAggregate(SMSGatewayConfigurationRepository smsGatewayConfigurationRepository) {
+		super();
+		this.smsGatewayConfigurationRepository = smsGatewayConfigurationRepository;
+	}
+	
+	@CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO)
+	@Transactional
+	@EventEmitter(selectorName = NotificationEventConstants.SELECTOR_NAME, selectorValue = NotificationEventConstants.POST_SMS_CONFIGURATION)
+	public String createSMSConfiguration(final CreateSMSConfigurationCommand createSMSConfigurationCommand) {
+		SMSConfiguration smsConfiguration = createSMSConfigurationCommand.getSMSConfiguration();
+		final SMSGatewayConfigurationEntity entity = SMSConfigurationMapper.map(smsConfiguration);
+		this.smsGatewayConfigurationRepository.save(entity);
+		
+		return smsConfiguration.getIdentifier();
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/mapper/EmailConfigurationMapper.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/mapper/EmailConfigurationMapper.java
new file mode 100644
index 0000000..d9c5649
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/mapper/EmailConfigurationMapper.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.cn.notification.service.internal.mapper;
+
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.service.internal.repository.EmailGatewayConfigurationEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class EmailConfigurationMapper {
+	
+	private EmailConfigurationMapper() {
+		super();
+	}
+	
+	public static EmailConfiguration map(final EmailGatewayConfigurationEntity emailGatewayConfigurationEntity) {
+		final EmailConfiguration emailConfiguration = new EmailConfiguration();
+		emailConfiguration.setIdentifier(emailGatewayConfigurationEntity.getIdentifier());
+		emailConfiguration.setHost(emailGatewayConfigurationEntity.getHost());
+		emailConfiguration.setPort(emailGatewayConfigurationEntity.getPort());
+		emailConfiguration.setUsername(emailGatewayConfigurationEntity.getUsername());
+		emailConfiguration.setApp_password(emailGatewayConfigurationEntity.getApp_password());
+		return emailConfiguration;
+	}
+	
+	public static EmailGatewayConfigurationEntity map(final EmailConfiguration emailConfiguration) {
+		final EmailGatewayConfigurationEntity emailGatewayConfigurationEntity = new EmailGatewayConfigurationEntity();
+		emailGatewayConfigurationEntity.setIdentifier(emailConfiguration.getIdentifier());
+		emailGatewayConfigurationEntity.setHost(emailConfiguration.getHost());
+		emailGatewayConfigurationEntity.setPort(emailConfiguration.getPort());
+		emailGatewayConfigurationEntity.setProtocol(emailConfiguration.getProtocol());
+		emailGatewayConfigurationEntity.setApp_password(emailConfiguration.getApp_password());
+		emailGatewayConfigurationEntity.setUsername(emailConfiguration.getUsername());
+		emailGatewayConfigurationEntity.setSmtp_auth(emailConfiguration.getSmtp_auth());
+		emailGatewayConfigurationEntity.setStart_tls(emailConfiguration.getStart_tls());
+		emailGatewayConfigurationEntity.setState(emailConfiguration.getState());
+		return emailGatewayConfigurationEntity;
+	}
+	
+	public static List<EmailConfiguration> map(final List<EmailGatewayConfigurationEntity> emailGatewayConfigurationEntity) {
+		final ArrayList<EmailConfiguration> emailConfigurationList = new ArrayList<>(emailGatewayConfigurationEntity.size());
+		emailConfigurationList.addAll(emailGatewayConfigurationEntity.stream().map(EmailConfigurationMapper::map).collect(Collectors.toList()));
+		return emailConfigurationList;
+	}
+	
+}
+
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/mapper/SMSConfigurationMapper.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/mapper/SMSConfigurationMapper.java
new file mode 100644
index 0000000..60418e8
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/mapper/SMSConfigurationMapper.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.mapper;
+
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.apache.fineract.cn.notification.service.internal.repository.SMSGatewayConfigurationEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SMSConfigurationMapper {
+	
+	private SMSConfigurationMapper() {
+		super();
+	}
+	
+	public static SMSConfiguration map(final SMSGatewayConfigurationEntity smsGatewayConfigurationEntity) {
+		final SMSConfiguration smsConfiguration = new SMSConfiguration();
+		smsConfiguration.setIdentifier(smsGatewayConfigurationEntity.getIdentifier());
+		smsConfiguration.setAccount_sid(smsGatewayConfigurationEntity.getAccount_sid());
+		smsConfiguration.setAuth_token(smsGatewayConfigurationEntity.getAuth_token());
+		smsConfiguration.setSender_number(smsGatewayConfigurationEntity.getSender_number());
+		smsConfiguration.setState(smsGatewayConfigurationEntity.getState());
+		return smsConfiguration;
+	}
+	
+	public static SMSGatewayConfigurationEntity map(final SMSConfiguration smsConfiguration) {
+		final SMSGatewayConfigurationEntity smsGatewayConfigurationEntity = new SMSGatewayConfigurationEntity();
+		smsGatewayConfigurationEntity.setIdentifier(smsConfiguration.getIdentifier());
+		smsGatewayConfigurationEntity.setAccount_sid(smsConfiguration.getAccount_sid());
+		smsGatewayConfigurationEntity.setAuth_token(smsConfiguration.getAuth_token());
+		smsGatewayConfigurationEntity.setSender_number(smsConfiguration.getSender_number());
+		smsGatewayConfigurationEntity.setState(smsConfiguration.getState());
+		return smsGatewayConfigurationEntity;
+	}
+	
+	public static List<SMSConfiguration> map(final List<SMSGatewayConfigurationEntity> smsGatewayConfigurationEntity) {
+		final ArrayList<SMSConfiguration> smsConfigurationList = new ArrayList<>(smsGatewayConfigurationEntity.size());
+		smsConfigurationList.addAll(smsGatewayConfigurationEntity.stream().map(SMSConfigurationMapper::map).collect(Collectors.toList()));
+		return smsConfigurationList;
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/EmailGatewayConfigurationEntity.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/EmailGatewayConfigurationEntity.java
new file mode 100644
index 0000000..2697a2b
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/EmailGatewayConfigurationEntity.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.repository;
+
+import javax.persistence.*;
+
+@SuppressWarnings("unused")
+@Entity
+@Table(name = "wada_email_gateway_configurations")
+public class EmailGatewayConfigurationEntity {
+	
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	@Column(name = "id")
+	private Long id;
+	@Column(name = "identifier")
+	private String identifier;
+	@Column(name = "host")
+	private String host;
+	@Column(name = "port")
+	private String port;
+	@Column(name = "username")
+	private String username;
+	@Column(name = "app_password")
+	private String app_password;
+	@Column(name = "protocol")
+	private String protocol;
+	@Column(name = "smtp_auth")
+	private String smtp_auth;
+	@Column(name = "start_tls")
+	private String start_tls;
+	@Column(name = "state")
+	private String state;
+	
+	public EmailGatewayConfigurationEntity() {
+		super();
+	}
+	
+	public Long getId() {
+		return id;
+	}
+	
+	public void setId(Long id) {
+		this.id = id;
+	}
+	
+	public String getIdentifier() {
+		return this.identifier;
+	}
+	
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+	
+	public String getHost() {
+		return host;
+	}
+	
+	public void setHost(String host) {
+		this.host = host;
+	}
+	
+	public String getPort() {
+		return port;
+	}
+	
+	public void setPort(String port) {
+		this.port = port;
+	}
+	
+	public String getProtocol() {
+		return protocol;
+	}
+	
+	public void setProtocol(String protocol) {
+		this.protocol = protocol;
+	}
+	
+	public String getUsername() {
+		return username;
+	}
+	
+	public void setUsername(String username) {
+		this.username = username;
+	}
+	
+	public String getApp_password() {
+		return app_password;
+	}
+	
+	public void setApp_password(String app_password) {
+		this.app_password = app_password;
+	}
+	
+	public String getSmtp_auth() {
+		return smtp_auth;
+	}
+	
+	public void setSmtp_auth(String smtp_auth) {
+		this.smtp_auth = smtp_auth;
+	}
+	
+	public String getStart_tls() {
+		return start_tls;
+	}
+	
+	public void setStart_tls(String start_tls) {
+		this.start_tls = start_tls;
+	}
+	
+	public String getState() {
+		return state;
+	}
+	
+	public void setState(String state) {
+		this.state = state;
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/EmailGatewayConfigurationRepository.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/EmailGatewayConfigurationRepository.java
new file mode 100644
index 0000000..1a5af4c
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/EmailGatewayConfigurationRepository.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.cn.notification.service.internal.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface EmailGatewayConfigurationRepository extends JpaRepository<EmailGatewayConfigurationEntity, Long> {
+	Optional<EmailGatewayConfigurationEntity> findByIdentifier(String identifier);
+	
+	@Query("SELECT CASE WHEN COUNT(c) > 0 THEN 'true' ELSE 'false' END FROM EmailGatewayConfigurationEntity c WHERE c.identifier = :identifier")
+	Boolean existsByIdentifier(@Param("identifier") final String identifier);
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/SMSGatewayConfigurationEntity.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/SMSGatewayConfigurationEntity.java
new file mode 100644
index 0000000..dcf3301
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/SMSGatewayConfigurationEntity.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.repository;
+
+import javax.persistence.*;
+
+@SuppressWarnings("unused")
+@Entity
+@Table(name = "wada_sms_gateway_configurations")
+public class SMSGatewayConfigurationEntity {
+	
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	@Column(name = "id")
+	private Long id;
+	@Column(name = "identifier")
+	private String identifier;
+	@Column(name = "account_sid")
+	private String account_sid;
+	@Column(name = "auth_token")
+	private String auth_token;
+	@Column(name = "sender_number")
+	private String sender_number;
+	@Column(name = "state")
+	private String state;
+	
+	public SMSGatewayConfigurationEntity() {
+		super();
+	}
+	
+	public Long getId() {
+		return id;
+	}
+	
+	public void setId(Long id) {
+		this.id = id;
+	}
+	
+	public String getIdentifier() {
+		return this.identifier;
+	}
+	
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+	
+	public String getAuth_token() {
+		return auth_token;
+	}
+	
+	public void setAuth_token(String auth_token) {
+		this.auth_token = auth_token;
+	}
+	
+	public String getAccount_sid() {
+		return account_sid;
+	}
+	
+	public void setAccount_sid(String account_sid) {
+		this.account_sid = account_sid;
+	}
+	
+	public String getState() {
+		return state;
+	}
+	
+	public void setState(String state) {
+		this.state = state;
+	}
+	
+	public String getSender_number() {
+		return sender_number;
+	}
+	
+	public void setSender_number(String sender_number) {
+		this.sender_number = sender_number;
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/SMSGatewayConfigurationRepository.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/SMSGatewayConfigurationRepository.java
new file mode 100644
index 0000000..ebac1c7
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/SMSGatewayConfigurationRepository.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.cn.notification.service.internal.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface SMSGatewayConfigurationRepository extends JpaRepository<SMSGatewayConfigurationEntity, Long> {
+	Optional<SMSGatewayConfigurationEntity> findByIdentifier(String identifier);
+	
+	@Query("SELECT CASE WHEN COUNT(c) > 0 THEN 'true' ELSE 'false' END FROM SMSGatewayConfigurationEntity c WHERE c.identifier = :identifier")
+	Boolean existsByIdentifier(@Param("identifier") final String identifier);
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/TemplateEntity.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/TemplateEntity.java
new file mode 100644
index 0000000..c699b9c
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/TemplateEntity.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.repository;
+
+import javax.persistence.*;
+import java.util.Objects;
+
+@SuppressWarnings("unused")
+@Entity
+@Table(name = "wada_templates")
+public class TemplateEntity {
+	
+	@Id
+	@GeneratedValue(strategy = GenerationType.IDENTITY)
+	@Column(name = "id")
+	private Long id;
+	@Column(name = "identifier")
+	private String identifier;
+	@Column(name = "event")
+	private String event;
+	@Column(name = "url")
+	private String url;
+	
+	
+	public TemplateEntity() {
+		super();
+	}
+	
+	public Long getId() {
+		return id;
+	}
+	
+	public void setId(Long id) {
+		this.id = id;
+	}
+	
+	public String getIdentifier() {
+		return this.identifier;
+	}
+	
+	public void setIdentifier(final String identifier) {
+		this.identifier = identifier;
+	}
+	
+	public String getEvent() {
+		return event;
+	}
+	
+	public void setEvent(String event) {
+		this.event = event;
+	}
+	
+	public String getUrl() {
+		return url;
+	}
+	
+	public void setUrl(String url) {
+		this.url = url;
+	}
+	
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+		if (o == null || getClass() != o.getClass()) return false;
+		TemplateEntity that = (TemplateEntity) o;
+		return Objects.equals(id, that.id) &&
+				Objects.equals(identifier, that.identifier) &&
+				Objects.equals(event, that.event) &&
+				Objects.equals(url, that.url);
+	}
+	
+	@Override
+	public int hashCode() {
+		return Objects.hash(id, identifier, event, url);
+	}
+	
+	@Override
+	public String toString() {
+		return "TemplateEntity{" +
+				"id=" + id +
+				", identifier='" + identifier + '\'' +
+				", event='" + event + '\'' +
+				", url='" + url + '\'' +
+				'}';
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/TemplateRepository.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/TemplateRepository.java
new file mode 100644
index 0000000..5e82d1f
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/repository/TemplateRepository.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.cn.notification.service.internal.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface TemplateRepository extends JpaRepository<TemplateEntity, Long> {
+	Optional<TemplateEntity> findByIdentifier(String identifier);
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/EmailService.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/EmailService.java
new file mode 100644
index 0000000..14ee02d
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/EmailService.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.service;
+
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.mail.MailException;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.stereotype.Component;
+
+import java.util.Properties;
+
+@Component
+public class EmailService {
+	
+	private Logger logger;
+	
+	
+	@Autowired
+	public EmailService(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+		super();
+		this.logger = logger;
+	}
+	
+	public void sendEmail(String from, String to, String subject, String message) {
+		
+		JavaMailSender sender = getJavaMailSender();
+		try {
+			SimpleMailMessage mail = new SimpleMailMessage();
+			mail.setFrom(from);
+			mail.setTo(to);
+			mail.setSubject(subject);
+			mail.setText(message);
+			sender.send(mail);
+		} catch (MailException exception) {
+			logger.debug("Caused by:" + exception.getCause().toString());
+		}
+	}
+	
+	public JavaMailSender getJavaMailSender() {
+		
+		JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
+		mailSender.setHost("smtp.gmail.com");
+		mailSender.setPort(587);
+		mailSender.setUsername("fineractcnnotificationdemo@gmail.com");
+		//mailSender.setPassword("pnuugpwmcibipdpw");
+		mailSender.setPassword("fineractcnnotification");
+		
+		Properties properties = mailSender.getJavaMailProperties();
+		properties.put(ServiceConstants.MAIL_TRANSPORT_PROTOCOL_PROPERTY,
+				ServiceConstants.MAIL_TRANSPORT_PROTOCOL_VALUE);
+		properties.put(ServiceConstants.MAIL_SMTP_AUTH_PROPERTY,
+				ServiceConstants.MAIL_SMTP_AUTH_VALUE);
+		properties.put(ServiceConstants.MAIL_SMTP_STARTTLS_ENABLE_PROPERTY,
+				ServiceConstants.MAIL_SMTP_STARTTLS_ENABLE_VALUE);
+		mailSender.setJavaMailProperties(properties);
+		
+		return mailSender;
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/NotificationService.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/NotificationService.java
new file mode 100644
index 0000000..8b25f1b
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/NotificationService.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.service;
+
+import org.apache.fineract.cn.customer.api.v1.domain.Customer;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.apache.fineract.cn.notification.service.internal.mapper.EmailConfigurationMapper;
+import org.apache.fineract.cn.notification.service.internal.mapper.SMSConfigurationMapper;
+import org.apache.fineract.cn.notification.service.internal.repository.EmailGatewayConfigurationRepository;
+import org.apache.fineract.cn.notification.service.internal.repository.SMSGatewayConfigurationRepository;
+import org.apache.fineract.cn.notification.service.internal.service.helperservice.CustomerAdaptor;
+import org.apache.fineract.cn.notification.service.internal.service.helperservice.NotificationAuthentication;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class NotificationService {
+	private final SMSService smsService;
+	private final EmailService emailService;
+	
+	private final SMSGatewayConfigurationRepository smsGatewayConfigurationRepository;
+	private final EmailGatewayConfigurationRepository emailGatewayConfigurationRepository;
+	
+	private final NotificationAuthentication notificationAuthentication;
+	private final CustomerAdaptor customerAdaptor;
+	private final Logger logger;
+	
+	private final String configureIdentifier = "Twilio";
+	
+	@Autowired
+	public NotificationService(final SMSGatewayConfigurationRepository smsGatewayConfigurationRepository,
+	                           final EmailGatewayConfigurationRepository emailGatewayConfigurationRepository,
+	                           final CustomerAdaptor customerAdaptor,
+	                           final SMSService smsService,
+	                           final EmailService emailService,
+	                           final NotificationAuthentication notificationAuthentication,
+	                           @Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger
+	) {
+		super();
+		this.smsGatewayConfigurationRepository = smsGatewayConfigurationRepository;
+		this.emailGatewayConfigurationRepository = emailGatewayConfigurationRepository;
+		this.customerAdaptor = customerAdaptor;
+		this.smsService = smsService;
+		this.emailService = emailService;
+		this.notificationAuthentication = notificationAuthentication;
+		this.logger = logger;
+		this.logger.debug("{} has been initiated", this.getClass());
+	}
+	
+	
+	public List<SMSConfiguration> findAllActiveSMSConfigurationEntities() {
+		return SMSConfigurationMapper.map(this.smsGatewayConfigurationRepository.findAll());
+	}
+	
+	public List<EmailConfiguration> findAllActiveEmailConfigurationEntities() {
+		return EmailConfigurationMapper.map(this.emailGatewayConfigurationRepository.findAll());
+	}
+	
+	public Optional<SMSConfiguration> findSMSConfigurationByIdentifier(final String identifier) {
+		return this.smsGatewayConfigurationRepository.findByIdentifier(identifier).map(SMSConfigurationMapper::map);
+	}
+	
+	
+	public Optional<EmailConfiguration> findEmailConfigurationByIdentifier(final String identifier) {
+		return this.emailGatewayConfigurationRepository.findByIdentifier(identifier).map(EmailConfigurationMapper::map);
+	}
+	
+	public Optional<Customer> findCustomer(final String customerIdentifier, String tenant) {
+		notificationAuthentication.authenticate(tenant);
+		return this.customerAdaptor.findCustomer(customerIdentifier);
+	}
+	
+	public Boolean smsConfigurationExists(final String identifier) {
+		return this.smsGatewayConfigurationRepository.existsByIdentifier(identifier);
+	}
+	
+	public Boolean emailConfigurationExists(final String identifier) {
+		return this.emailGatewayConfigurationRepository.existsByIdentifier(identifier);
+	}
+	
+	public void configureSMSSender() {
+		SMSConfiguration configuration = findSMSConfigurationByIdentifier(configureIdentifier).get();
+		smsService.configure(configuration.getAccount_sid(),
+				configuration.getAuth_token(),
+				configuration.getSender_number());
+	}
+	
+	public void sendSMS(String receiver, String template) {
+		this.smsService.sendSMS(receiver, template);
+	}
+	
+	public void sendEmail(String from, String to, String subject, String message) {
+		this.emailService.sendEmail(from, to, subject, message);
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/SMSService.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/SMSService.java
new file mode 100644
index 0000000..fca2476
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/SMSService.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.service;
+
+
+import com.twilio.Twilio;
+import com.twilio.rest.api.v2010.account.Message;
+import com.twilio.rest.api.v2010.account.MessageCreator;
+import com.twilio.type.PhoneNumber;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SMSService {
+	
+	private final Logger logger;
+	@Value("${smssender.accountSID}")
+	private String ACCOUNT_SID;
+	@Value("${smssender.authToken}")
+	private String AUTH_TOKEN;
+	@Value("${smssender.senderNumber}")
+	private String SENDERNUMBER;
+	
+	@Autowired
+	public SMSService(@Qualifier(ServiceConstants.LOGGER_NAME) Logger logger) {
+		super();
+		this.logger = logger;
+	}
+	
+	public void configure(String accountSID,
+	                      String authToken,
+	                      String senderNumber) {
+		ACCOUNT_SID = accountSID;
+		AUTH_TOKEN = authToken;
+		SENDERNUMBER = senderNumber;
+	}
+	
+	public void sendSMS(String receiver, String template) {
+		this.logger.debug("sendSMS invoked");
+		Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
+		MessageCreator messageCreator = Message.creator(ACCOUNT_SID,
+				new PhoneNumber(receiver),
+				new PhoneNumber(SENDERNUMBER),
+				template);
+		Message message = messageCreator.create();
+		System.out.println(message.getSid());
+	}
+}
\ No newline at end of file
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/helperservice/CustomerAdaptor.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/helperservice/CustomerAdaptor.java
new file mode 100644
index 0000000..33a79f4
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/helperservice/CustomerAdaptor.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.service.helperservice;
+
+import org.apache.fineract.cn.customer.api.v1.client.CustomerManager;
+import org.apache.fineract.cn.customer.api.v1.client.CustomerNotFoundException;
+import org.apache.fineract.cn.customer.api.v1.domain.Customer;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+@Service
+public class CustomerAdaptor {
+	
+	private final Logger logger;
+	private final CustomerManager customerManager;
+	
+	@Autowired
+	public CustomerAdaptor(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+	                       final CustomerManager customerManager) {
+		super();
+		this.logger = logger;
+		this.customerManager = customerManager;
+	}
+	
+	public Optional<Customer> findCustomer(final String customerIdentifier) {
+		try {
+			final Customer customer = this.customerManager.findCustomer(customerIdentifier.replaceAll("\"", ""));
+			return Optional.of(customer);
+		} catch (final CustomerNotFoundException cnfex) {
+			this.logger.warn("Customer {} not found.", customerIdentifier.replaceAll("\"", ""));
+		}
+		return Optional.empty();
+	}
+}
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/helperservice/NotificationAuthentication.java b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/helperservice/NotificationAuthentication.java
new file mode 100644
index 0000000..62eec05
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/internal/service/helperservice/NotificationAuthentication.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.internal.service.helperservice;
+
+/*
+ ebenezergraham created on 8/4/18
+*/
+
+import org.apache.fineract.cn.api.util.UserContextHolder;
+import org.apache.fineract.cn.identity.api.v1.client.IdentityManager;
+import org.apache.fineract.cn.identity.api.v1.domain.Authentication;
+import org.apache.fineract.cn.lang.TenantContextHolder;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
+
+@Component
+public class NotificationAuthentication {
+	private final String USER_PASSWORD = "shingi";
+	private final String USER_IDENTIFIER = "wadaadmin";
+	
+	private IdentityManager identityManager;
+	private Logger logger;
+	
+	@Autowired
+	public NotificationAuthentication(IdentityManager identityManager,
+	                                  @Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+		this.identityManager = identityManager;
+		this.logger = logger;
+	}
+	
+	public void authenticate(String tenant) {
+		TenantContextHolder.clear();
+		TenantContextHolder.setIdentifier(tenant);
+		
+		final Authentication authentication =
+				this.identityManager.login(USER_IDENTIFIER, Base64Utils.encodeToString(USER_PASSWORD.getBytes()));
+		UserContextHolder.clear();
+		UserContextHolder.setAccessToken(USER_IDENTIFIER, authentication.getAccessToken());
+	}
+}
\ No newline at end of file
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/listener/CustomerEventListener.java b/service/src/main/java/org/apache/fineract/cn/notification/service/listener/CustomerEventListener.java
new file mode 100644
index 0000000..c6f85b3
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/listener/CustomerEventListener.java
@@ -0,0 +1,275 @@
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one
+     * or more contributor license agreements.  See the NOTICE file
+     * distributed with this work for additional information
+     * regarding copyright ownership.  The ASF licenses this file
+     * to you under the Apache License, Version 2.0 (the
+     * "License"); you may not use this file except in compliance
+     * with the License.  You may obtain a copy of the License at
+     *
+     *   http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing,
+     * software distributed under the License is distributed on an
+     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+     * KIND, either express or implied.  See the License for the
+     * specific language governing permissions and limitations
+     * under the License.
+     */
+    package org.apache.fineract.cn.notification.service.listener;
+
+    import org.apache.fineract.cn.customer.api.v1.CustomerEventConstants;
+    import org.apache.fineract.cn.customer.api.v1.domain.ContactDetail;
+    import org.apache.fineract.cn.customer.api.v1.domain.Customer;
+    import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+    import org.apache.fineract.cn.notification.service.ServiceConstants;
+    import org.apache.fineract.cn.notification.service.internal.service.NotificationService;
+    import org.slf4j.Logger;
+    import org.springframework.beans.factory.annotation.Autowired;
+    import org.springframework.beans.factory.annotation.Qualifier;
+    import org.springframework.jms.annotation.JmsListener;
+    import org.springframework.messaging.handler.annotation.Header;
+    import org.springframework.stereotype.Component;
+
+    @SuppressWarnings("unused")
+    @Component
+    public class CustomerEventListener {
+	    private final NotificationService notificationService;
+	    private final Logger logger;
+	
+	    @Autowired
+	    public CustomerEventListener(final NotificationService notificationService,
+	                                 @Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+		    this.logger = logger;
+		    this.notificationService = notificationService;
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_POST_CUSTOMER
+	    )
+	    public void customerCreatedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                     final String payload) {
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		    this.logger.debug("{} has been invoked", "customerCreatedEvent");
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\nYour account has been created\n\nBest Regards,\n Your MFI");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account created", "Dear Valued Customer,\n\n Your account has been created\n\nBest Regards,\nMFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_PUT_CUSTOMER
+	    )
+	    public void customerUpdatedEvents(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                      final String payload) {
+		    this.logger.debug("{} has been invoked", "customerUpdatedEvents");
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\nYour account has been Updated\\n\\nBest Regards,\\n Your MFI\"");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account created", "Dear Valued Customer,\n\nYour account has been Updated\n\nBest Regards,\n Your MFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_ACTIVATE_CUSTOMER
+	    )
+	    public void customerActivatedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                       final String payload) {
+		    this.logger.debug("{} has been invoked", "customerActivatedEvent");
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equalsIgnoreCase(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\n Your account has been Activated\n\nBest Regards,\n Your MFI");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account created", "Dear Valued Customer,\n\nYour account has been Activated\n\nBest Regards,\n Your MFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_LOCK_CUSTOMER
+	    )
+	    public void customerLockedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                    final String payload) {
+		    this.logger.debug("{} has been invoked", "customerLockedEvent");
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE)) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\nYour account has been Locked");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL)) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account created", "Dear Valued Customer,\n\nYour account has been Locked\n\nBest Regards,\n Your MFI");
+			    }
+		    });
+	    }
+	
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_UNLOCK_CUSTOMER
+	    )
+	    public void customerUnlockedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                      final String payload) {
+		    this.logger.debug("{} has been invoked", "customerUnlockedEvent");
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\nYour account has been Unlocked");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account created", "Dear Valued Customer,\n\nYour account has been Unlocked\n\nBest Regards,\n Your MFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_CLOSE_CUSTOMER
+	    )
+	    public void customerClosedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                    final String payload) {
+		    this.logger.debug("{} has been invoked", "customerClosedEvent");
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\nYour account has been Closed\n\nBest Regards\nYour MFI");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account created", "Dear Valued Customer,\n\nYour account has been Closed\n\nBest Regards,\n Your MFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_REOPEN_CUSTOMER
+	    )
+	    public void customerReopenedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                      final String payload) {
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber, "Dear Valued Customer,\n\nYour account has been reopened");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com", emailAddress, "Account Reopened", "Dear Valued Customer,\n\nYour account has been reopened\n\nBest Regards,\n Your MFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_PUT_CONTACT_DETAILS
+	    )
+	    public void contactDetailsChangedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                           final String payload) {
+		    this.logger.debug("{} has been invoked", "contactDetailsChangedEvent");
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber,
+						    "Dear Valued Customer," +
+								    "\n\nYour contact has been changed successfully" +
+								    "\nNew Contact: "+receiverNumber+
+								    "\n\nBest Regards," +
+								    "\n Your MFI");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com",
+						    emailAddress,
+						    "Contact Details Changed" +
+								    "New Contact: "+emailAddress,
+						    "Dear Valued Customer,\n\nYour contact has been changed successfully\n\nBest Regards\nMFI");
+			    }
+		    });
+	    }
+	
+	    @JmsListener(
+			    destination = CustomerEventConstants.DESTINATION,
+			    selector = CustomerEventConstants.SELECTOR_PUT_ADDRESS
+	    )
+	    public void addressChangedEvent(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                                    final String payload) {
+		    Customer customer = this.notificationService.findCustomer(payload, tenant).get();
+		
+		    customer.getContactDetails().forEach(contact -> {
+			    if (contact.getType().equals(ContactDetail.Type.PHONE.toString())) {
+				    String receiverNumber = contact.getValue();
+				    notificationService.sendSMS(receiverNumber,
+						    "Dear Valued Customer," +
+								    "\n\nYour address has been changed successfully" +
+								    "\nStreet: "+customer.getAddress().getStreet()+
+								    "\nCity: "+customer.getAddress().getCity()+
+								    "\nState: "+customer.getAddress().getRegion()+
+								    "\nCountry: "+customer.getAddress().getCountry()+
+								    "\n\nBest Regards," +
+								    "\n Your MFI");
+			    } else if (contact.getType().equals(ContactDetail.Type.EMAIL.toString())) {
+				    String emailAddress = contact.getValue();
+				    // TODO: Localize message
+				    // TODO: Pass message to template
+				    notificationService.sendEmail("fineractcnnotificationdemo@gmail.com",
+						    emailAddress,
+						    "Contact Details Changed" +
+								    "New Contact: "+emailAddress,
+						    "Dear Valued Customer," +
+								    "\n\nYour address has been changed successfully" +
+								    "\nStreet: "+customer.getAddress().getStreet()+
+								    "\nCity: "+customer.getAddress().getCity()+
+								    "\nState: "+customer.getAddress().getRegion()+
+								    "\nCountry: "+customer.getAddress().getCountry()+
+								    "\n\nBest Regards" +
+								    "\nMFI");
+			    }
+		    });
+	    }
+    }
\ No newline at end of file
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/listener/PortfolioEventListener.java b/service/src/main/java/org/apache/fineract/cn/notification/service/listener/PortfolioEventListener.java
new file mode 100644
index 0000000..2f860e5
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/listener/PortfolioEventListener.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.listener;
+
+import org.apache.fineract.cn.individuallending.api.v1.events.IndividualLoanEventConstants;
+import org.apache.fineract.cn.lang.config.TenantHeaderFilter;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.apache.fineract.cn.notification.service.internal.service.NotificationService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author Ebenezer Graham
+ */
+@SuppressWarnings("unused")
+@Component
+public class PortfolioEventListener {
+	
+	private final NotificationService notificationService;
+	private final Logger logger;
+	
+	@Autowired
+	public PortfolioEventListener(
+			final NotificationService notificationService,
+			@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger) {
+		super();
+		this.logger = logger;
+		this.notificationService = notificationService;
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_OPEN_INDIVIDUALLOAN_CASE
+	)
+	public void onOpen(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                   final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_DENY_INDIVIDUALLOAN_CASE
+	)
+	public void onDeny(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                   final String payload) {
+		this.notificationService.sendSMS("+23058409206",
+				"Dear Valued Customer,\n\nYour loan request has been denied\n\nBest Regards\nYour MFI");
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_APPROVE_INDIVIDUALLOAN_CASE
+	)
+	public void onApprove(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                      final String payload) {
+		logger.info(payload);
+		this.notificationService.sendSMS("+23058409206",
+				"Dear Valued Customer,\n\nYour loan has been Approved and waiting disbursal\n\nBest Regards\nYour MFI");
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_DISBURSE_INDIVIDUALLOAN_CASE
+	)
+	public void onDisburse(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                       final String payload) {
+		logger.info(payload);
+		this.notificationService.sendSMS("+23058409206",
+			"Dear Valued Customer,\n\nYour loan has been disbursed\n\nBest Regards\nYour MFI");
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_APPLY_INTEREST_INDIVIDUALLOAN_CASE
+	)
+	public void onApplyInterest(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                            final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_ACCEPT_PAYMENT_INDIVIDUALLOAN_CASE
+	)
+	public void onAcceptPayment(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                            final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_CHECK_LATE_INDIVIDUALLOAN_CASE
+	)
+	public void onCheckLate(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                        final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_MARK_LATE_INDIVIDUALLOAN_CASE
+	)
+	public void onMarkLate(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                       final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_MARK_IN_ARREARS_INDIVIDUALLOAN_CASE
+	)
+	public void onMarkInArrears(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                            final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_WRITE_OFF_INDIVIDUALLOAN_CASE
+	)
+	public void onWriteOff(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                       final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_CLOSE_INDIVIDUALLOAN_CASE
+	)
+	public void onClose(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                    final String payload) {
+	}
+	
+	@JmsListener(
+			subscription = IndividualLoanEventConstants.DESTINATION,
+			destination = IndividualLoanEventConstants.DESTINATION,
+			selector = IndividualLoanEventConstants.SELECTOR_RECOVER_INDIVIDUALLOAN_CASE
+	)
+	public void onRecover(@Header(TenantHeaderFilter.TENANT_HEADER) final String tenant,
+	                      final String payload) {
+	}
+}
\ No newline at end of file
diff --git a/service/src/main/java/org/apache/fineract/cn/notification/service/rest/NotificationRestController.java b/service/src/main/java/org/apache/fineract/cn/notification/service/rest/NotificationRestController.java
new file mode 100644
index 0000000..df36f03
--- /dev/null
+++ b/service/src/main/java/org/apache/fineract/cn/notification/service/rest/NotificationRestController.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.notification.service.rest;
+
+import org.apache.fineract.cn.anubis.annotation.AcceptedTokenType;
+import org.apache.fineract.cn.anubis.annotation.Permittable;
+import org.apache.fineract.cn.command.gateway.CommandGateway;
+import org.apache.fineract.cn.lang.ServiceException;
+import org.apache.fineract.cn.notification.api.v1.PermittableGroupIds;
+import org.apache.fineract.cn.notification.api.v1.client.ConfigurationNotFoundException;
+import org.apache.fineract.cn.notification.api.v1.domain.EmailConfiguration;
+import org.apache.fineract.cn.notification.api.v1.domain.SMSConfiguration;
+import org.apache.fineract.cn.notification.service.ServiceConstants;
+import org.apache.fineract.cn.notification.service.internal.command.CreateEmailConfigurationCommand;
+import org.apache.fineract.cn.notification.service.internal.command.CreateSMSConfigurationCommand;
+import org.apache.fineract.cn.notification.service.internal.command.InitializeServiceCommand;
+import org.apache.fineract.cn.notification.service.internal.command.PostSMSCommand;
+import org.apache.fineract.cn.notification.service.internal.service.NotificationService;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@SuppressWarnings("unused")
+@RestController
+@RequestMapping("/")
+public class NotificationRestController {
+	
+	private final Logger logger;
+	private final CommandGateway commandGateway;
+	private final NotificationService notificationService;
+	
+	@Autowired
+	public NotificationRestController(@Qualifier(ServiceConstants.LOGGER_NAME) final Logger logger,
+	                                  final CommandGateway commandGateway,
+	                                  final NotificationService notificationService) {
+		super();
+		this.logger = logger;
+		this.commandGateway = commandGateway;
+		this.notificationService = notificationService;
+	}
+	
+	@Permittable(value = AcceptedTokenType.SYSTEM)
+	@RequestMapping(
+			value = "/initialize",
+			method = RequestMethod.POST,
+			consumes = MediaType.ALL_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	ResponseEntity<Void> initialize() throws InterruptedException {
+		this.commandGateway.process(new InitializeServiceCommand());
+		return ResponseEntity.accepted().build();
+	}
+	
+	@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.SELF_MANAGEMENT)
+	@RequestMapping(
+			value = "/notification/sms/active",
+			method = RequestMethod.GET,
+			consumes = MediaType.ALL_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	List<SMSConfiguration> findAllActiveSMSConfigurationEntities() {
+		return this.notificationService.findAllActiveSMSConfigurationEntities();
+	}
+	
+	@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.SELF_MANAGEMENT)
+	@RequestMapping(
+			value = "/notification/email/active",
+			method = RequestMethod.GET,
+			consumes = MediaType.ALL_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	List<EmailConfiguration> findAllActiveEmailConfigurationEntities() {
+		return this.notificationService.findAllActiveEmailConfigurationEntities();
+	}
+	
+	@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.SELF_MANAGEMENT)
+	@RequestMapping(
+			value = "/notification/sms/{identifier}",
+			method = RequestMethod.GET,
+			consumes = MediaType.ALL_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	ResponseEntity<SMSConfiguration> findSMSConfigurationByIdentifier(@PathVariable("identifier") final String identifier)
+	throws ConfigurationNotFoundException {
+		return this.notificationService.findSMSConfigurationByIdentifier(identifier)
+				.map(ResponseEntity::ok)
+				.orElseThrow(() -> ServiceException.notFound("SMS Gateway Configuration with identifier " + identifier + " doesn't exist."));
+	}
+	
+	@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.SELF_MANAGEMENT)
+	@RequestMapping(
+			value = "/notification/email/{identifier}",
+			method = RequestMethod.GET,
+			consumes = MediaType.ALL_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	ResponseEntity<EmailConfiguration> findEmailConfigurationByIdentifier(@PathVariable("identifier") final String identifier)
+			throws ConfigurationNotFoundException {
+		return this.notificationService.findEmailConfigurationByIdentifier(identifier)
+				.map(ResponseEntity::ok)
+				.orElseThrow(() -> ServiceException.notFound("Email Gateway Configuration with identifier " + identifier + " doesn't exist."));
+	}
+	
+	@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.SELF_MANAGEMENT)
+	@RequestMapping(
+			value = "/notification/sms/create",
+			method = RequestMethod.POST,
+			consumes = MediaType.APPLICATION_JSON_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	ResponseEntity<Void> createSMSConfiguration(@RequestBody @Valid final SMSConfiguration smsConfiguration) throws InterruptedException {
+		if (this.notificationService.smsConfigurationExists(smsConfiguration.getIdentifier())) {
+			throw ServiceException.conflict("Configuration {0} already exists.", smsConfiguration.getIdentifier());
+		}
+		
+		this.commandGateway.process(new CreateSMSConfigurationCommand(smsConfiguration));
+		return ResponseEntity.accepted().build();
+	}
+	
+	@Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.SELF_MANAGEMENT)
+	@RequestMapping(
+			value = "/notification/email/create",
+			method = RequestMethod.POST,
+			consumes = MediaType.APPLICATION_JSON_VALUE,
+			produces = MediaType.APPLICATION_JSON_VALUE
+	)
+	public
+	@ResponseBody
+	ResponseEntity<Void> createEmailConfiguration(@RequestBody @Valid final EmailConfiguration emailConfiguration) throws InterruptedException {
+		if (this.notificationService.emailConfigurationExists(emailConfiguration.getIdentifier())) {
+			throw ServiceException.conflict("Configuration {0} already exists.", emailConfiguration.getIdentifier());
+		}
+		this.commandGateway.process(new CreateEmailConfigurationCommand(emailConfiguration));
+		return ResponseEntity.accepted().build();
+	}
+}
diff --git a/service/src/main/resources/application.yml b/service/src/main/resources/application.yml
new file mode 100644
index 0000000..fa7165e
--- /dev/null
+++ b/service/src/main/resources/application.yml
@@ -0,0 +1,88 @@
+#
+# 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.
+#
+
+spring:
+  cloud:
+    discovery:
+      enabled: false
+    config:
+      enabled: false
+    mail:
+      host: smtp.gmail.com
+      port: 587
+      username:
+      password:
+      properties:
+        debug: true
+        mail:
+          smtp:
+            auth: true
+            starttls:
+              enable: true
+
+
+
+eureka:
+  client:
+    serviceUrl:
+      defaultZone: http://localhost:8761/eureka/
+
+server:
+  port: 8081
+  contextPath: /notification/v1/*
+
+cassandra:
+  clusterName: staging_cluster
+  contactPoints: 127.0.0.1:9042,127.0.0.2:9042,127.0.0.3:9042
+  keyspace: seshat
+  cl:
+    read: LOCAL_QUORUM
+    write: LOCAL_QUORUM
+    delete: LOCAL_QUORUM
+
+mariadb:
+  driverClass: org.mariadb.jdbc.Driver
+  database: seshat
+  host: localhost
+  port: 3306
+  user: root
+  password: mysql
+
+bonecp:
+  idleMaxAgeInMinutes: 240
+  idleConnectionTestPeriodInMinutes: 60
+  maxConnectionsPerPartition: 10
+  minConnectionsPerPartition: 1
+  partitionCount: 2
+  acquireIncrement: 5
+  statementsCacheSize: 100
+
+async:
+  corePoolSize: 32
+  maxPoolSize: 16384
+  queueCapacity: 0
+  threadName: async-processor-
+
+flyway:
+  enabled: false
+
+smssender:
+  accountSID: AC1fde2c6f26f367b93231c5fdb944c908
+  authToken: bc9a53e41745b8471e0ecafc859d86aa
+  senderNumber: +1 510-944-1898
diff --git a/service/src/main/resources/bootstrap.yml b/service/src/main/resources/bootstrap.yml
new file mode 100644
index 0000000..76c2441
--- /dev/null
+++ b/service/src/main/resources/bootstrap.yml
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+spring:
+    application:
+        name: notification-v1
diff --git a/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
new file mode 100644
index 0000000..57cefe1
--- /dev/null
+++ b/service/src/main/resources/db/migrations/mariadb/V1__initial_setup.sql
@@ -0,0 +1,56 @@
+--
+-- 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.
+--
+
+-- -----------------------------------------------------
+-- Table wada_sms_gateway_configurations
+-- -----------------------------------------------------
+CREATE TABLE wada_sms_gateway_configurations (
+  id INT(11) NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(45) NULL DEFAULT NULL,
+  account_sid VARCHAR(255) NOT NULL,
+  auth_token VARCHAR(255) NOT NULL,
+  sender_number VARCHAR(45) NOT NULL,
+  state VARCHAR(45) NULL DEFAULT NULL,
+  PRIMARY KEY (id));
+
+-- -----------------------------------------------------
+-- Table wada_email_gateway_configurations
+-- -----------------------------------------------------
+CREATE TABLE wada_email_gateway_configurations (
+  id INT(11) NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(45) NULL DEFAULT NULL,
+  host VARCHAR(45) NOT NULL,
+  port VARCHAR(45) NOT NULL,
+  username VARCHAR(45) NOT NULL,
+  app_password VARCHAR(255) NOT NULL,
+  protocol VARCHAR(45)NOT NULL,
+  smtp_auth VARCHAR (45)NOT NULL,
+  start_tls VARCHAR (45)NOT NULL,
+  state VARCHAR(45)NOT NULL,
+  PRIMARY KEY (id));
+
+-- -----------------------------------------------------
+-- Table wada_templates
+-- -----------------------------------------------------
+CREATE TABLE wada_templates (
+  id INT(11) NOT NULL AUTO_INCREMENT,
+  identifier VARCHAR(45) NULL DEFAULT NULL,
+  event VARCHAR(45) NULL DEFAULT NULL,
+  url VARCHAR(255) NOT NULL,
+  PRIMARY KEY (id));
diff --git a/service/src/main/resources/db/migrations/mariadb/V2__sms_gateway_configurations.sql b/service/src/main/resources/db/migrations/mariadb/V2__sms_gateway_configurations.sql
new file mode 100644
index 0000000..d795f01
--- /dev/null
+++ b/service/src/main/resources/db/migrations/mariadb/V2__sms_gateway_configurations.sql
@@ -0,0 +1,20 @@
+--
+-- 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.
+--
+
+INSERT INTO wada_sms_gateway_configurations VALUES ('1', 'Twilio', 'AC1fde2c6f26f367b93231c5fdb944c908', 'c9a53e41745b8471e0ecafc859d86aa', '+1 510-944-1898', 'ACTIVE');
\ No newline at end of file
diff --git a/service/src/main/resources/db/migrations/mariadb/V3__email_gateway_configurations.sql b/service/src/main/resources/db/migrations/mariadb/V3__email_gateway_configurations.sql
new file mode 100644
index 0000000..9482b7c
--- /dev/null
+++ b/service/src/main/resources/db/migrations/mariadb/V3__email_gateway_configurations.sql
@@ -0,0 +1,20 @@
+--
+-- 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.
+--
+
+INSERT INTO wada_email_gateway_configurations VALUES ('1', 'Gmail', 'smtp.gmail.com', '587','fineractcnnotificationdemo@gmail.com', 'pnuugpwmcibipdpw', 'smtp', 'true', 'true', 'ACTIVE');
\ No newline at end of file
diff --git a/service/src/main/resources/logback.xml b/service/src/main/resources/logback.xml
new file mode 100644
index 0000000..5cd9b4c
--- /dev/null
+++ b/service/src/main/resources/logback.xml
@@ -0,0 +1,58 @@
+<!--
+
+    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.
+
+-->
+<configuration>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>logs/notification.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <fileNamePattern>logs/archive/notification.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <maxHistory>7</maxHistory>
+            <totalSizeCap>2GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="io" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="net" level="INFO">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <root level="DEBUG">
+        <appender-ref ref="FILE"/>
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..868411f
--- /dev/null
+++ b/settings.gradle
@@ -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.
+ */
+
+rootProject.name = 'notification'
+
+includeBuild 'api'
+includeBuild 'service'
+includeBuild 'component-test'
+
diff --git a/shared.gradle b/shared.gradle
new file mode 100644
index 0000000..6b000b7
--- /dev/null
+++ b/shared.gradle
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+group 'org.apache.fineract.cn.notification'
+version '0.1.0-BUILD-SNAPSHOT'
+
+ext.versions = [
+        fineractcnidentity      : '0.1.0-BUILD-SNAPSHOT',
+        fineractcnoffice        : '0.1.0-BUILD-SNAPSHOT',
+        fineractcncustomer      : '0.1.0-BUILD-SNAPSHOT',
+        fineractcnaccounting    : '0.1.0-BUILD-SNAPSHOT',
+        fineractcnportfolio     : '0.1.0-BUILD-SNAPSHOT',
+        fineractcnteller        : '0.1.0-BUILD-SNAPSHOT',
+        fineractcnpayroll       : '0.1.0-BUILD-SNAPSHOT',
+        fineractcngroup         : '0.1.0-BUILD-SNAPSHOT',
+        frameworkapi            : '0.1.0-BUILD-SNAPSHOT',
+        frameworklang           : '0.1.0-BUILD-SNAPSHOT',
+        frameworkasync          : '0.1.0-BUILD-SNAPSHOT',
+        frameworkcassandra      : '0.1.0-BUILD-SNAPSHOT',
+        frameworkmariadb        : '0.1.0-BUILD-SNAPSHOT',
+        frameworkcommand        : '0.1.0-BUILD-SNAPSHOT',
+        frameworktest           : '0.1.0-BUILD-SNAPSHOT',
+        frameworkanubis         : '0.1.0-BUILD-SNAPSHOT',
+        validator               : '5.3.0.Final',
+        springjavamail          : '1.4.1.RELEASE',
+        twilioapi               : '7.17.+'
+]
+
+apply plugin: 'java'
+apply plugin: 'idea'
+apply plugin: 'maven-publish'
+apply plugin: 'io.spring.dependency-management'
+
+tasks.withType(JavaCompile) {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+repositories {
+    jcenter()
+    mavenLocal()
+}
+
+dependencyManagement {
+    imports {
+        mavenBom 'io.spring.platform:platform-bom:Athens-RELEASE'
+        mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Camden.SR1'
+    }
+}
+
+// override certain dependency provided by Spring platform using newer releases
+ext['cassandra.version'] = '3.6'
+ext['cassandra-driver.version'] = '3.1.2'
+ext['activemq.version'] = '5.13.2'
+ext['spring-data-releasetrain.version'] = 'Gosling-SR2A'
+
+dependencies {
+    compile(
+            [group: 'com.google.code.findbugs', name: 'jsr305']
+    )
+
+    testCompile(
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-test']
+    )
+}
+
+jar {
+    from sourceSets.main.allSource
+    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+}
+
+license {
+    header rootProject.file('../HEADER')
+    strictCheck true
+    mapping {
+        java = 'SLASHSTAR_STYLE'
+        xml = 'XML_STYLE'
+        yml = 'SCRIPT_STYLE'
+        yaml = 'SCRIPT_STYLE'
+    }
+}
+
+rat {
+    // List of exclude directives, defaults to ['**/.gradle/**']
+    excludes = [
+            "**/.idea/**",
+            "**/.gradle/**",
+            "**/gradle/**",
+            "**/build/**",
+            "gradlew",
+            "gradlew.bat",
+            "README.md"
+    ]
+}
+


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services