How to connect Firebase Realtime Database using Mule 4
Firebase Realtime Database is a cloud-hosted NoSQL database that stores data in JSON format. It is more frequently used by Mobile applications as a backend data store. In this article, we will learn how we can integrate Mule 4 to connect Firebase Realtime Database and perform data operations.
1. About Firebase
Firebase Realtime Database is a cloud-hosted NoSQL database that stores data in JSON format. Below image of my Firebase console shows a Firebase Database with a JSON collection test-user
that contain some JSON objects.
Firebase SDK allows below operations -
-
Set (or replace) a value of JSON node.
-
Update some of the keys at give path without replacing all the content
-
Push a new JSON node to the collection at given path. This generates an unique key for new value.
-
Listen to any changes to the data at given path.
-
Query a node value at given path.
If you wan’t to learn more about Firebase Realtime Database, I suggest you read this documentation.
1.1 Authentication for Firebase
We would need a Firebase Service Account Key file for authentication. After creating your Firebase Project on Firebase console, you can create a Service Account Key for Firebase Admin SDK from here.
2. Mule 4 Firebase Connector
Mule SDK is an another powerful addition to Mule ecosystem with the release of Mule 4. Using the Extension mechanism provided by new SDK, I created a Mule 4 Connector for interacting with Firebase Realtime Database.
To add this connector to a Mule 4 application, you just need to add below dependency in your project maven POM file -
<dependency>
<groupId>com.javastreets</groupId>
<artifactId>mule-firebase-connector</artifactId>
<version>0.0.2</version>
<classifier>mule-plugin</classifier> (1)
</dependency>
1 | It is important to specify mule-plugin as a classifier, so that Anypoint Studio recognizes the connector at design time. |
Once you add it, you should see a new Firebase
module in Mule Palette window -
3. Firebase Configuration and Operation
3.1 Global Configuration
First thing we need is a Global Configuration which will contain the Firebase Realtime Database Connection information.
-
Servie Account Key File: Provide the path to JSON file downloaded from Firebase Console.
-
Firebase Database URL: A Unique url to your database eg. test.firebaseio.com
-
Firebase Application Name: This MUST be unique for each Firebase Config.
3.2 Push Data
This operation allows us to add a new key-value pair to a collection. It will auto generate the key and return it as a payload after the successful operation.
For example, when called on test-user
collection, it would insert a new JSON Object in the collection. The Logger after push operation should print the newly generated key.
<sub-flow name="mule4-firebase-demo-push-data" doc:id="45789a8d-fc47-4274-b8fa-36531d7b497b">
<ee:transform doc:name="Transform Message"
doc:id="4ee3b32d-dddc-4661-a804-692d60278d50">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/java
---
{
"randomId": random() * 100
}]]></ee:set-payload>
</ee:message>
</ee:transform>
<firebase:database-push-data doc:name="Database: Push Data"
doc:id="85b6682a-386b-4751-87ea-688486bb3eb3" config-ref="FirebaseDatabase_Config"
refPath="test-user" content="#[payload]" />
<logger level="INFO" doc:name="Logger"
doc:id="19d57e81-1759-41ec-9a8e-4b10ed205f63" message="#['Pushed new Object with key :' ++ payload]" />
<set-variable value="#[payload]" doc:name="Set Variable"
doc:id="7583f2a8-e3bd-4074-a833-f0cb2df96e4a" variableName="pushKey" />
</sub-flow>
3.3 Update Data
This operation allows us to add or modify some attributes of a node, without replacing all the content of it. While Push operation will replace the content, update operation will help to perform partial updates.
The input to this operation is a map of reference path and its value. To add a Name
property under newly generated record under test-user
, reference path will be the of format {key}/Name
and value would be the Name to be updated. For example, {'-LDJuYqLolLemQXM6zmY/Name' : 'Manik'}
.
This operation does not return any value.
Reference Path is a JSON-P like path to a specific node in the JSON database. Eg. test-user/some-key
|
<sub-flow name="mule4-firebase-demo-update-data" doc:id="023bafbc-9c2a-403e-8100-8d53dde07b26">
<logger level="INFO" doc:name="Logger"
doc:id="e011763a-8c27-4eb2-8ece-af7fb7a43137" message="#['Updating Record with key : ' ++ payload]" />
<ee:transform doc:name="Transform Message"
doc:id="772a1b74-bf7f-4e42-bf49-0e2b300f3965">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/java
---
{
(payload ++ "/Name"): "Manik"
}]]></ee:set-payload>
</ee:message>
</ee:transform>
<firebase:database-update-data doc:name="Database: Update Data"
doc:id="55619fb6-e7a5-4ec5-b023-7e3badf7401c" config-ref="FirebaseDatabase_Config"
refPath="test-user" content="#[payload]">
</firebase:database-update-data>
</sub-flow>
3.4 Query Data
As name indicates, this queries for data at given reference path and returns it as Payload.
<sub-flow name="mule4-firebase-demo-query-data" doc:id="a5876994-6311-4cf1-b157-babd618017dd">
<firebase:database-query-data doc:name="Database: Query Data"
doc:id="de821b5b-2af0-4388-90e0-eef0b30bfa4c" config-ref="FirebaseDatabase_Config"
refPath="#['test-user']" />
<logger level="INFO" doc:name="Logger"
doc:id="962de731-2334-48e1-9862-ebfdd405affc" message="#[payload]" />
</sub-flow>
3.5 Listen to Changes in Database
This operation implements the Change Data Capture (CDC) for listening to any changes to child nodes under given Reference Path.
This is a Mule Source and can trigger flow execution when data is received.
It listens for four child events -
-
CHILD_ADDED
-
CHILD_CHANGED
-
CHILD_REMOVED
-
CHILD_MOVED
When listener starts, Firebase will first push an individual CHILD_ADDED event for all existing nodes and then will emit the event when new node is added. Firebase SDK does not provide a way to listen for all new changes when Runtime starts. See Event Type documentation here. |
Attributes: When an event is received, it add attributes as shown below. The event type can be retrieved as attributes.eventType
which would have one of the four value specified above.
Payload: Payload should contain three values related to target child -
-
previousKey which is a Key of a child appearing before the current target child
-
key of a current target child
-
value of a current target child
Below flow listens to any changes to test-user
collection:
<flow name="mule4-firebase-demoFlow1" doc:id="948db0e7-1f14-46ea-9720-fc43effb0ad8">
<firebase:database-child-listener
doc:name="Database: Child Listener" doc:id="28b04356-f49b-4aad-819a-793616357e8b"
config-ref="FirebaseDatabase_Config" refPath="test-user" />
<logger level="INFO" doc:name="Logger"
message="#[attributes.eventType ++ ' : ' ++ payload.key]" />
<logger level="INFO" doc:name="Logger"
doc:id="30b89bae-dcfa-4661-94da-d365b4208335" message="#[payload]" />
<error-handler>
<on-error-propagate enableNotifications="true"
logException="true" doc:name="On Error Propagate" doc:id="11189de8-314b-4ee7-830e-ca44af1e5f70">
<logger level="INFO" doc:name="Logger"
doc:id="3bda8c1a-cde2-41a1-be2d-7e19cf266465" message="#[error]" />
</on-error-propagate>
</error-handler>
</flow>
Event Guarantees of Firebase: The Firebase Database guarantees all the events generated. In case the remote connection to database is lost, it continues to operate with local manager. When remote connection establishes, it automatically synchronizes the state with remote database. |
5. Conclusion
Mule 4 SDK can easily be used to extend Mule Runtime for adding new Connectors. We have seen how we can connect to Firebase Realtime Database using Mule 4 and perform data operations.
The Demo source code is available on Github.
Connector source is also available on Github. Please feel free to add any issues related to connector on Github.
Stay updated!
On this blog, I post articles about different technologies like Java, MuleSoft, and much more.
You can get updates for new Posts in your email by subscribing to JavaStreets feed here -
Lives on Java Planet, Walks on Java Streets, Read/Writes in Java, JCP member, Jakarta EE enthusiast, MuleSoft Integration Architect, MuleSoft Community Ambassador, Open Source Contributor and Supporter, also writes at Unit Testers, A Family man!