Build an end to end Notification Gateway for SMS and Push Notifications using AWS SNS, AWS SQS, Firebase and Spring Boot
What is the purpose of Notification Gateway?
Notification Gateway will act as a standalone application that will be able to send different types of notifications across platform. Any project/service that wants to send notifications will just have to post a request to Notification Gateway.
Input Request Body
The request body will contain following fields :
- Message : This is the notification message.
- Recipient Address : This is the address of the recipient. For SMS, it will be a phone number with country code. For email, it will be an email id. For mobile push notifications, it will be the mobile’s device id.
- Notification Type : This indicates the type of notification you are sending i.e. push, sms or email.
Architecture of Notification Gateway
Architecture Diagram Sequence Flow
- Notification Gateway receives a Notification Request containing notification text, notification type and recipient address.
- A publisher service in notification gateway will forward this request to an already created AWS SNS Topic. This topic will already have all the SQS queues subscribed to it. SNS will then do filtering of the notification request based on notification type and then pass the request to respective queue in SQS.
- A receiver service in Notification Gateway will continuously poll messages from the different SQS queues. As soon as it receives any new notification request, it creates a proper message format out of it based on the notification type.
- The receiver service then passes the newly created message to an SNS ARN. SNS then gets the recipient id from it and sends it to the target device.
AWS Environment setup
Before starting coding, we first need to set up the AWS environment. For that we first need an AWS account. Once we have it, we then need to choose a region where our services will be running. Some regions don’t allow sms/push notification. So, you must select a region which allows all types of notifications. ( Eg. Ireland )
1. Creation of SNS topic for fanout and filter of incoming notifications to SQS
◈ Sign in to the Amazon SNS console.
◈ In the Create topic section, enter a Topic name, for example
MyTopic
.◈ Choose Create topic.
◈ The topic is created and the
MyTopic
page is displayed.◈ The topic’s Name, ARN, (optional) Display name, and Topic owner’s AWS account ID are displayed in the Details section.
◈ Copy the topic ARN to the clipboard, for example:
arn:aws:sns:us-east-2:123456789012:MyTopic
2. Creation a Standard SQS Queues
We will be creating three separate queues for sms notification, push notification and email notification.
◈ Sign in to the Amazon SQS console.
◈ Choose Create New Queue.
◈ On the Create New Queue page, ensure that you’re in the correct region and then type the Queue Name.
◈ Standard is selected by default.
◈ Click choose Quick-Create Queue.
After creating all three queues, your SQS console would look like this :
On selecting any queue, you will be able to get the Queue properties including ARN and URL.
◈ From the list of queues, check all the queues you have just created.
◈ Click Queue Actions and select Subscribe Queues to SNS Topic.
◈ The Subscribe to a Topic dialog box is displayed. From the Choose a Topic drop-down list, select your topic created earlier, which you want to subscribe your three queues to. Because you created the SNS topic from the same account, it shows up in the list.
If the SNS topic was made by another account, you could subscribe to it by using the Topic ARN field. For more details, see the Amazon SNS documentation orCross-Account Integration with SNS.
3. Creation of subscription filter policy for SQS queues (created in step 2) in SNS Topic (created in step 1)
◈ Navigate to the SNS console.
◈ Open the topic that you created in step 1.
◈ Under Subscriptions tab, you will find separate subscription for all the queues you subscribed to this SNS topic in last step.
◈ Click on the id of each of these subscriptions, then click on edit filtering policy
Under edit subscription filter policy, -> paste below for email subscription:{“notification_type”: [“email”]}-> paste below for push subscription:{“notification_type”: [“push”]}-> paste below for sms subscription:{“notification_type”: [“sms”]}
4. Creation of Platform Application in SNS ( only for sending push notifications to Android devices ).
◈ Navigate to the SNS console.
◈ Click on the Push Notification tab on left side bar.
◈ Click on Create Platform Application.
◈ Enter any application name.
◈ Under the Push notification platform select Firebase Cloud Messaging ( FCM ).
◈ Under the API key box, enter the Server Key of the Firebase project. ( check next excerpt for the steps to get Firebase Server Key ).
Firebase Environment Setup ( Only for push notifications in Android devices )
◈ Navigate to the Firebase console and sign in.
◈ Create a new project.
◈ Open the project and navigate to Project Setting. Then click on cloud messaging.
◈ Note down the Server key from Project credentials.
Spring Boot Code
Since we are done with setting up the environment, let’s move towards the Spring Boot coding part.
Before starting to code, you need to install AWS cli on your system and setup your IDE such that it is able to communicate to your AWS account. I will skip it here as there are various tutorials already on the internet for it.
We start with creating a configuration class. The purpose is to successfully connect with AWS.
Then we create a model class to define the incoming notification message structure.
Then we create a post endpoint in the controller to receive the notification.
Then we create an interface for service
Then we add the implementation for the service interface we created
You can see that we have used a constant class to store all the constants. It is a good practice to keep the constants in a separate class.
The above classes are sufficient to receive the notification, filter it based on notification type and send it to SNS which will then forward it to respective SQS queues.
For that you just need to hit your endpoint from Postman or any other similar application. The body of the request will contain notificationText, recipientId, notificationType. In case of sms notifications, recipientId will be phone number with country code. Also, do verify that there is no such service as DND activated on your number. For push notifications, recipient Id will be the device’s token Id. Check the last section of the article to fetch token Id of Android devices.
Now, we will create another Spring Boot project that will continuously poll notifications from these queues and send it to respective target devices.
Similar to the above project, we first create the config class.
Let’s create the same model class to define the incoming notification message structure.
Then in the main class we use Command Line Runner to call our service.
We create an interface for SqsPullService
Then we write the implementation of this service
Now we will be sending sms notification and push notification. Therefore, let’s write the interface for it.
PushNotificationService
SmsNotificationService
Let’s write the implementation of these services
PushNotificationServiceImpl
Finally we put the constant’s class
Using the above codes you will be able to successfully deliver sms notifications. In order to deliver Android push notification, you also need to do some coding on the Android side where you will also need to put a google-services.json file in your Android side code. This google-services.json file, you will get from the project you created in Firebase.
Android side code ( only for Push Notification )
Our Android app will have a single screen with a button. The purpose of this button is to log the device token on the console. This device token will be the recipientId when sending the post request to the Notification Gateway as the device token uniquely identifies an Android device.
We start with creating our MainActivity.java class
We have another class to log the device token
We write our activity_main.xml. It just has a single button. On the button click, device token will be logged in console.
I will just paste the gradle dependencies required for your convenience.
dependencies {
implementation 'com.google.firebase:firebase-analytics:17.2.0'
implementation 'com.google.firebase:firebase-messaging:20.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.core:core:1.1.0'
// Add the SDKs for any other Firebase products you want to use in your app
// For example, to use Firebase Authentication and Cloud Firestore
implementation 'com.google.firebase:firebase-auth:19.1.0'
implementation 'com.google.firebase:firebase-firestore:21.1.1'
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
Last thing is to put your google-services.json file in the project.
That’s all you need to do. Using the above code you will be able to receive notifications in your Android app but the app should be in background. If you want notifications while app is in foreground, you need to implement onMessageReceived function in your code.
If you have any doubts, please do comment here or mail me on ksut28@gmail.com.
Also, feel free to suggest any improvement.