Integrate Your Realm App with Amazon EventBridge
Rate this tutorial
This post was developed with the help of AWS.
Realm makes it easy to develop compelling mobile applications backed by a serverless MongoDB Realm back end and the MongoDB Atlas database service. You can enrich those applications by integrating with AWS's broad ecosystem of services. In this article, we'll show you how to configure Realm and AWS to turn Atlas database changes into Amazon EventBridge events – all without adding a single line of code. Once in EventBridge, you can route events to other services which can act on them.
We'll use an existing mobile chat application (RChat). RChat creates new
ChatMessage
objects which Realm Sync writes to the ChatMessage Atlas collection. Realm also syncs the chat message with all other members of the chat room.
This post details how to add a new feature to the RChat application – forwarding messages to a Slack channel.
We'll add a Realm Trigger that forwards any new
ChatMessage
documents to EventBridge. EventBridge stores those events in an event bus, and a rule will route it to a Lambda function. The Lambda function will use the Slack SDK (using credentials we'll store in AWS Secrets Manager).Amazon EventBridge is a serverless event bus that makes it easier to connect applications together using data from your applications, integrated software as a service (SaaS) applications, and AWS services. It does so by delivering a stream of real-time data from various event sources. You can set up routing rules to send data to targets like AWS Lambda and build loosely coupled application architectures that react in near-real time to data sources.
If you want to build and run the app for yourself, this is what you'll
need:
- Mac OS 11+
- iOS 14.2+ (a real device, or the simulator built into Xcode)
- (Free) MongoDB account
If you're not interested in running the mobile app (or don't have access to a Mac), the article includes instructions on manually adding a document that will trigger an event being sent to EventBridge.
This walkthrough shows you how to:
If you don't already have a MongoDB cloud account, create one. You'll also create an Atlas organization and project as you work through the wizard. For this walkthrough, you can use the free tier. Stick with the defaults (e.g., "Cluster Name" = "Cluster0") but set the version to MongoDB 4.4.
While your database cluster is starting, select "Project Access" under "Access Manager." Create an API key with "Project Owner" permissions. Add your current IP address to the access list. Make a note of the API keys; they're needed when using realm-cli.
Wait until the Atlas cluster is running.
From a terminal, import the back end Realm application (substituting in your Atlas project's API keys) using realm-cli:
From the Atlas UI, click on the Realm logo and you will see the RChat app. Open it and make a note of the Realm "App Id":

Optionally, create database indexes by using mongorestore to import the empty database from the
dump
folder.The Slack app simply allows us to send a message to a Slack channel.
Navigate to the Slack API page. (You'll need to log in or register a new account if you don't have one.)
Click on the button to create a new Slack app, name it "RChat," and select one of your Slack workspaces. (If using your company's account, you may want or need to create a new workspace.)
Give your app a short description and then click "Save Changes."
After creating your Slack app, select the "OAuth & Permissions" link. Scroll down to "Bot Token Scopes" and add the
chat.write
and channels:read
scopes.Click on "Install to Workspace" and then "Allow."
Take a note of the new "Bot User OAuth Access Token."
From your Slack client, create a new channel named "rchat-notifications." Invite your Slack app bot to the channel (i.e., send a message from the channel to "@RChat Messenger" or whatever Slack name you gave to your app):

You now need to find its channel ID from a terminal window (substituting in your Slack OAuth access token):
In the results, you'll find an entry for your new "rchat-notifications" channel. Take a note of its
id
; it will be stored in AWS Secrets Manager and then used from the Lambda function when calling the Slack SDK:EventBridge supports MongoDB as a partner event source; this makes it very easy to receive change events from Realm Triggers.
From the EventBridge console, select "Partner event sources." Search for the "MongoDB" partner and click "Set up":

Take a note of your AWS account ID.
Return to the Realm UI navigate to "Triggers" and click "Add a trigger." Configure the trigger as shown here:

Rather than sticking with the default "Function" event type (which is
Realm Function, not to be confused with Lambda), select "EventBridge,"
add your AWS Account ID from the previous section, and click "Save"
followed by "REVIEW & DEPLOY":

Return to the AWS "Partner event sources" page, select the new source, and click "Associate with event bus":

On the next screen, leave the "Resource-based policy" empty.
Returning to the "Event buses" page, you'll find the new MongoDB partner bus.
We need a new Lambda function to be invoked on any MongoDB change events added to the event bus. That function will use the Slack API to send messages to our channel. The Lambda function must provide the OAuth token and channel ID to use the Slack SDK. Rather than storing that private information in the function, it's more secure to hold them in AWS Secrets Manager.
Navigate to the Secrets Manager console and click "Store a new secret." Add the values you took a note of when creating the Slack app:

Click through the wizard, and apart from assigning a unique name to the secret (and take a note of it as it's needed when configuring the Lambda function), leave the other fields as they are. Take a note of the ARN for the new secret as it's required when configuring the Lambda function.
From the Lambda console, click "Create Function." Name the function "sendToSlack" and set the runtime to "Node.js 12.x."
After creating the Lambda function, navigate to the "Permissions" tab and click on the "Execution role" role name. On the new page, click on the "Policy name" and then "Edit policy."
Click "Add additional permissions" and select the "Secrets Manager" service:

Select the "ListSecrets" action. This permission allows the Lambda function to see what secrets are available, but not to read our specific Slack secret. To remedy that, click "Add additional permissions" again. Once more, select the "Secrets Manager" service, but this time select the "Read" access level and specify your secret's ARN in the resources section:

Review and save the new permissions.
Returning to the Lambda function, select the "Configuration" tab and add an environment variable to set the "secretName" to the name you chose when creating the secret (the function will use this to access Secret Manager):

It can take some time for the function to fetch the secret for the first time, so set the timeout to 30 seconds in the "Basic settings" section.
Finally, we can write the actual Lambda function.
From a terminal, bootstrap the function definition:
In the same lambda directory, create a file called
index.js
:There are a couple of things to call out in that code.
This is how the Slack credentials are fetched from Secret Manager:
event
is passed in as a parameter, and the function retrieves the original MongoDB document's contents from event.detail.fullDocument
.blocks
is optional, and if omitted, the SDK uses text as the body of the Slack message.Package up the Lambda function:
From the Lambda console, upload the zip file and then deploy:

The Lambda function is now complete, and the next section will start routing events from the EventBridge partner message bus to it.
The final step to integrate our Realm app with the new Lambda function is to have that function consume the events from the event bus. We do that by adding a new EventBridge rule.
Return to the EventBridge console and click the "Rules" link. Select the "aws.partner/mongodb.com/stitch.trigger/xxx" event bus and click "Create rule."
The "Name" can be anything. You should use an "Event pattern," set "Pre-defined pattern by service," search for "Service partner" "MongoDB," and leave the "Event pattern" as is. This rule matches all bus events linked to our AWS account (i.e., it will cover everything sent from our Realm function):

Select the new Lambda function as the target and click "Create":

After creating the back end Realm app, open the RChat iOS app in Xcode:
Navigate to
RChatApp.swift
. Replace rchat-xxxxx
with your Realm App Id:
Select your target device (a connected iPhone/iPad or one of the built-in simulators) and build and run the app with
⌘r
.To test a chat app, you need at least two users and two instances of the chat app running.
From Xcode, run (
⌘r
) the RChat app in one simulator, and then again in a second simulator after changing the target device. On each device, register a new user. As one user, create a new chat room (inviting the second user). Send messages to the chat room from either user, and observe that message also appearing in Slack:
Suppose you're not interested in using the iOS app or don't have access to a Mac. In that case, you can take a shortcut by manually adding documents to the
ChatMessage
collection within the RChat
database. Do this from the "Collections" tab in the Atlas UI. Click on "INSERT DOCUMENT" and then ensure that you include fields for "author" and "text":
This post stepped through how to get your data changes from MongoDB into your AWS ecosystem with no new code needed. Once your EventBridge bus has received the change events, you can route them to one or more services. Here we took a common approach by sending them to a Lambda function which then has the freedom to import external libraries and work with other AWS or external services.
To understand more about the Realm chat app that was the source of the messages, read Building a Mobile Chat App Using Realm – Data Architecture.
If you have questions, please head to our developer community website where the MongoDB engineers and the MongoDB community will help you build your next big idea with MongoDB.