MuleSoft Chat : Phone, Web and Mule !
Tags: mulesofthackathon, websockets, android, mulesoft
Published: 2020-11-22 19:33:54

**Everyday is an API Day**
MuleSoft is loaded with features. Mule runtime engine (Mule) is a lightweight integration engine that runs Mule applications and supports domains and policies. MuleSoft is well known for getting APIs and integrations done in short time.
I would like to demonstrate how I got a real time chat application working with MuleSoft.
Some components used:
1. HTTP 
2. Web Socket
3. Database
4. DataWeave

I have also created an **android application** that talks to MuleSoft WebSocket Server. Thus the end to end app allows users to join a room over android app or web. 😀🙌

### **WebSocket : two-way interactive communication**
WebSocket is a computer communications protocol, providing full-duplex communication channels over a single TCP connection, i.e both server and client can send messages across the network.
The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.

The solution is divided into two parts:
1. The System API to store data of users and handle room details
2. The Experience layer in form of a WebSocket Server

### **High Level Architecture**
![HLD](https://dev-to-uploads.s3.amazonaws.com/i/bhoo9uzule1rnokb4bdk.png)

### **System API Implementation**
The main aim of the system api is to give a CRUD based API interface to users and chat rooms.
I am using SQLite DB for this and we are good to use any persistence mechanism for this.

* The API specification(RAML):
  1. /users :
     * GET : This end point returns all the users registered to some chat room
     * POST : This end point is used to add a user to the persistent store
  2. /users/{userId}:     
     * GET : This end point returns the user with the URI Param userId
     * PUT : This end point is used to updated details of a user. Example: SocketId is generated only when user successfully joins any room.
     * DELETE : This end point is used to delete an user
  3. /room :
     * GET : This end point returns all the rooms where users are present
     * POST : This end point adds an user to a room
  4. /room/{roomId} :
     * GET : This endpoint is used to get all the users in the roomId
     * DELETE : This end point deletes a room

We can add more endpoints here to add enhance capabilities. For now we will stick to this minimal viable product.

```
#%RAML 1.0
title: mule-chat-sapi
description: Set of endpoints to add user and rooms for chat application

types:
  User: !include dataType/User.raml
  Room: !include dataType/Room.raml

/users:
  get:
    description: This endpoint is used to get all users
    responses:
      200:
        body:
          application/json:
            type: User[]
  post:
    description: This endpoint is used to add an user
    body:
      application/json:
        type: User
    responses:
      201:
        body:
          application/json:
            example: !include examples/users_post.json
  /{userId}:
      get:
        description: This endpoint is used to get a particular users
        responses:
          200:
            body:
              application/json:
                type: User
      put:
        description: This endpoint is used to update details of an already added user recognized by the userId
        body:
          application/json:
            type: User
        responses:
          200:
            body:
              application/json:
                example: !include examples/users_put.json
      delete:
        description: This endpoint is used to delete an user
        responses:
          200:
            body:
              application/json:
                example: !include examples/users_delete.json
/room:
  get:
    description: Get all room and user ids in the room
    responses:
      200:
        body:
          application/json:
            type: Room[]
  post:
    description: This endpoint is used to add an user to a room
    body:
      application/json:
        type: Room
    responses:
      201:
        body:
          application/json:
            example: !include examples/join_post.json
  /{roomId}:
    description: This endpoint is used to get all the users in the roomId
    get:
      responses:
        200:
          body:
            application/json:
              type: User[]
    delete:
        description: This endpoint is used to delete a room
        responses:
          200:
            body:
              application/json:
                example: !include examples/room_delete.json
```

* The Database:
SQLite is a relational database management system (RDBMS) contained in a C library. This has all the CRUD features. I am using this to show the Mule capability to handle any form of JDBC connection. Also using SQLite removes the dependency of hosting any Database solution. But we can connect the system API to any persistent mechanism like AWS RDS, IBM DB2, MySQL etc.
I am using a Generic Database connection:
![Generic Database Connection to SQLite](https://dev-to-uploads.s3.amazonaws.com/i/w0tz3uykwimbbjqo0jru.png)

The Driver class org.sqlite.JDBC comes from below Maven Dependency:
![SQLite JAR Maven Dependency](https://dev-to-uploads.s3.amazonaws.com/i/7eutx7axrmolbkd83ipv.png)

* API Implementation:
The API Implementation is a generic APIKit Router based solution and the database operations are coded as per requirement.

> Now we are done with our System API layer. It's now time to go into the interesting part of the solution which actually adds the WebSocket based chat feature.

### **Experience Layer : Mule Chat App**
This application also written in Mule and HTML, CSS, JS allows multiple users to join multiple rooms and start interacting with each other.

1. WebSocket:
The WebSocket specification defines an API establishing "socket" connections between a web browser and a server. In plain words: There is an persistent connection between the client and the server and both parties can start sending data at any time.
Unlike the method where client polls for data every time, Websocket allows server to push data to client as and when available.

2. WebSocket Implementation:
   * WebSocket(WSS) HTTPS Listener:
     We create a HTTPS Listener with port 8082. This will be used by the WebSockets to communicate over the channel.
     ![HTTPS Listener](https://dev-to-uploads.s3.amazonaws.com/i/4ohdwpwg6nl3hsni68wu.PNG)
   * WebSocket(WSS) Mule Server:
     We use Mule, only as the Web Socket Server. The connection is WSS which is a secured Web Socket communication comparable to HTTPSThe configuration is below:
     ![Mule Server](https://dev-to-uploads.s3.amazonaws.com/i/zudirs830ydsxg3c6v0j.PNG)
     It's worth noting that I checked only the Server setting to make sure that it acts as WebSocket server.
   * WebSocket(WS) HTML/JS Client:
     The WebSocket client in this case is the web browser where users comes and logs to join multiple rooms and chat with people.
     ![HTML/JS Client](https://dev-to-uploads.s3.amazonaws.com/i/ah1kbxjkl4fz449kirsk.PNG)
     Here we used JavaScript to connect to the WebSocket over : wss://<webSocketURL>:8082/
Note that unlike http the protocol here is **wss**
    In the image highlighted above the highlighted boxes signifies below:
    * 1 : WebSocket is deployed over a shared Load Balancer, so we provide the internal worker URL with port.
    * 2 : We create the WebSocket URL that will be used. 
    * 3 : We establish a full duplex connection to Mule WebSocket Server.
    * 4 : Listens to incoming messages and adds the messages to the HTML DOM using custom javascript function insertChat()

3. WebSocket Mule Flow:
   * Initiate Connection:
     Whenever a user joins a room using Web Client, this flow is triggered and it updates the socketId of the user.
     ![Initiate Connection Flow](https://dev-to-uploads.s3.amazonaws.com/i/jycmo4p73h2l4ttfnhv3.PNG)
   * Route Messages:
     Mule is well known for routing messages using it's connector, here I route the appropriate messages to users in a room.
     ![Route Messages](https://dev-to-uploads.s3.amazonaws.com/i/9vnyzi9z0vqpjw2xr6i9.PNG)
   * Close Connection:
     When user closes the browser, this flow is called and it removes user from the table
     ![Close Connection](https://dev-to-uploads.s3.amazonaws.com/i/6dzjt9koniqw5qxcwry6.PNG)

> This pretty much covers the WebSocket implementation.

For connecting to the System APIs to add/remove room and users I have used the connector published to exchange as below:
![Mule Chat SAPI](https://dev-to-uploads.s3.amazonaws.com/i/lummh3bptvwnkk22cwnp.PNG)

Below are the images of the working solution:
> Enter Room Id or Number and Join Room

![Room](https://dev-to-uploads.s3.amazonaws.com/i/bqf09wuvrx4hlcnrnxzt.png)

> Add name and avatar image(This appears in the Chat UI)

![User](https://dev-to-uploads.s3.amazonaws.com/i/hfi0t5lsz4nhw191m0ue.PNG)

> Send Chat Messages and enjoy interacting!

![Chat](https://dev-to-uploads.s3.amazonaws.com/i/2dkbixbfchihxnenennq.PNG)

* Web UI (Mule Flow)

MuleSoft is well known for hosting APIs and integration but it can also be used to host your UI application and serve it as the frontend.
For the Chat UI, I am using Parse Template.
     ![Join Chat](https://dev-to-uploads.s3.amazonaws.com/i/gwdswbxnnkelypzq19do.PNG)
     Here, I fetch the Room Id from query parameters and set it in variable. Then use it to dynamically to generate HTML content using Parse Template.

* Android UI

The native android application allows user to join a room by entering Room Number, name and an optional avatar link. In case user doesn't give a link to avatar the default robot image is considered.
![Join Room](https://dev-to-uploads.s3.amazonaws.com/i/tymsqqedghs4sui3fqmr.png)

The user can then interact 💬 with other users in same room connected using **Web** or **Android** Client 💻

![Interact](https://dev-to-uploads.s3.amazonaws.com/i/b6dh2j12caas3s300tsg.png)

### **Deployment**

The SAPI is deployed at : https://mule-chat-sapi.us-e2.cloudhub.io/console/

The WebSocket deployment actually needs Dedicated Load Balancer to work as sited here : (https://docs.mulesoft.com/websockets-connector/1.0/websockets-connector-cloudhub).
The trial account doesn't support VPC or DLB. So I am using self signed certificate and exposing internal worker URL.
The application can be accessed at : https://mule-worker-mule-chat-app.us-e2.cloudhub.io:8082/
You will see an error like below :
![App](https://dev-to-uploads.s3.amazonaws.com/i/7ei7k9hqro9faom5bgqn.PNG)
Since the certificates are self signed, it doesn't recognize and throw this error but you can click on **Proceed to mule-worker-mule-chat-app.us-e2.cloudhub.io (unsafe)** and start inviting your friends for a chat 😉
This can also be run on local Anypoint studio by importing jar from [Mule-Chat-App] (https://github.com/tirthankarkundu17/mule-chat-app/blob/master/mule-chat-app.jar?raw=true)
We can however get the DLB setup and deploy the chat application too.

The android app(apk) is hosted here to download and install : [Download] (https://github.com/tirthankarkundu17/mule-chat-app/blob/master/mulesoft-chat.apk?raw=true)

### **Demo**
**Updated** : Added a new Android interface to interact with WebSocket Mule Server.
{% youtube iBvMaByln8c%}

### **References and Code**

[RAML-Specification](https://anypoint.mulesoft.com/exchange/portals/abc-8534/0825c465-6fab-451f-9c20-9da1ac4d9560/mule-chat/)
Mule-Chat-SAPI [GitHub-Repo] (https://github.com/tirthankarkundu17/mule-chat-sapi)
Mule-Chat-App [GitHub-Repo] (https://github.com/tirthankarkundu17/mule-chat-app)
Android-App [Download] (https://github.com/tirthankarkundu17/mule-chat-app/blob/master/mulesoft-chat.apk?raw=true)

### **Future Prospects**

Suppose an API takes good amount of time to do some really resource intensive task, we can run an async operation at backend and then whenever data is ready we can send it back from Server to Client using the duplex channel. This is useful since client doesn't have to constantly poll the server for updates. Also, for cases like stock market ticks, this will be useful. Asynchronous messaging in going to be the next revolution in data delivery ✅
Can be integrated with Chatbots and a wide range of APIs to give a more enhanced experience.

### **About the author**

Tirthankar Kundu is a full stack developer who loves to code. He is MuleSoft Certified Developer who loves APIs. Proficient in both frontend and backend technologies. Working with Persistent Systems Ltd. as a Senior Mule developer in Insurance domain.
- :computer: [LinkedIn] (https://www.linkedin.com/in/kundutirthankar/)
- :book: [Medium] (https://medium.com/@tirthankarkundu)
- 📜 [Website] (https://bitmaskers.in)