Developing a Node.js WebSocket Chat Application to Oracle Application Container Cloud


Options



Before You Begin

Purpose

This tutorial shows you how to create a WebSocket server application with Node.js and a WebSocket client application with HTML5 and JavaScript. The result is a simple chat that sends messages to multiple clients.

Time to Complete

  • Server Development: 30 minutes
  • Client Development: 30 minutes
  • Cloud Deployment: 40 minutes

Background

With WebSocket, connections made to an HTTP server can be full-duplex and real-time, allowing the server and the client to exchange messages at any time with any content. This is different from the common HTTP request and response mechanism. With WebSocket, a request from the client might not generate an inmediate response from the server, and the server can push data to the client without a previous request.

Scenario

You create two separate applications: a Node.js server and an HTML5 and JavaScript client. To keep your files sorted and prevent confusion, you create two different folders and put the files of each application inside:

Project structure diagram
Description of this image

The WebSocket client/server is a simple web chat project that stores and propagates messages sent. Simultaneously connected clients can follow the chat in real time. Messages sent are stored in the server memory.

Client connection diagram
Description of this image

Before the client connects to the server, it asks the user for a user name. The client provides that user name when it connects to the server. The server then pushes all the previous messages to the newly connected client.

When a client sends a message, the server pushes the message to all clients, including the original sender.

Message exchange diagram
Description of this image

Messages are sent and received in JavaScript Object Notation (JSON) format:

{user:"UserName",text:"Message Body"}

The server doesn't process the actual message; it just propagates it to all the connected clients.

The message structure is used by the clients to format the message being displayed on the screen.

What Do You Need?

Developing the Node.js WebSocket Server

To develop a Node.js application, you need only to install Node.js and a text editor. NPM is bundled with Node.js. NPM is a utility that downloads and builds dependencies for your Node.js projects. NPM uses a file called package.json to store the dependency and project properties. NPM also has build and testing capabilities.

Node.js is sometimes referred to simply as Node.

  1. Open a console window and go to the folder where you want to store the Node WebSocket server.

    Console window
    Description of this image
  2. Run npm init to create the package.json file. When you are prompted, enter the following:

    • name: node-chat-server
    • version: 1.0.0 (or press Enter).
    • description: A simple node chat server
    • entry point: server.js
    • test command: Press enter.
    • git repository: Press enter.
    • keywords: Press enter.
    • author: Enter your name or email addess.
    • License: Press enter.

    You'll be asked to verify the information. If it's correct, then enter yes or press Enter.

    Console window
    Description of this image

    The package.json file is created and stored in the current folder. You can open it and modify it if needed.

  3. In the console window, install the web socket dependencies.

    npm install --save ws
    Console window
    Description of this image

    Note: Don't worry about warnings or errors in the process caused by dependencies on native binaries that couldn't be built. The libraries being used often have a JavaScript fallback node library and native binaries are used only to optimize performance. You can figure this out by looking at the console and finding the output: optional dep failed, continuing

    Console window
    Description of this image
  4. Open the generated package.json file in a text editor, and verify its contents. It should look like this:

    {
      "name": "node-chat-server",
      "version": "1.0.0",
      "description": "A simple node chat server",
      "main": "server.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "anna.smith@example.com",
      "license": "ISC",
      "dependencies": {
        "ws": "^0.8.0"
      }
    }
    
  5. Create a new server.js file and open it in a text editor.

  6. Add the following require statement to use the WebSocket Server component:

    var WebSocketServer = require('ws').Server;
  7. Add a PORT variable:

    var PORT = 8087;
  8. Create a WebSocketServer listening to the port:

    var wss = new WebSocketServer({port: PORT});
  9. Create a messages array to store all sent messages:

    var messages = [];
  10. Add the connection event listener to the wss:

    wss.on('connection', function (ws) {
      //add code here
    });
    
  11. Inside the wss connection event handler, add the following code to send all the messages to the newly connected client:

      messages.forEach(function(message){
    	ws.send(message);
      });
    
  12. Add the following code to add a listener to the client connection when a message is sent and to broadcast the messages to other clients:

      ws.on('message', function (message) {
    	messages.push(message);
        console.log('Message Received: %s', message);
        wss.clients.forEach(function (conn) {
          conn.send(message);
        });
      });

The completed server.js file:

var WebSocketServer = require('ws').Server;

var PORT = 8087;

var wss = new WebSocketServer({port: PORT});

var messages = [];
wss.on('connection', function (ws) {
  messages.forEach(function(message){
	ws.send(message);
  });
  ws.on('message', function (message) {
	messages.push(message);
    console.log('Message Received: %s', message);
    wss.clients.forEach(function (conn) {
      conn.send(message);
    });
  });
});

Developing the HTML5 and JavaScript WebSocket Client

To develop an HTML5 application with JavaScript, CSS3, and HTML you only need a text editor and a web browser.

  1. In a separate folder, create an empty index.html file and open it in a text editor.

  2. Add the following code to create a basic HTML5 page:

    <!DOCTYPE html>
    <html>
      <head>
        <title>MessageBoard</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script>
        </script>    
      </head>
      <body>
      </body>
    </html>

    Notice the empty script and body tags, you'll add JavaScript code to the script tag and the HTML layout to the body tag.

  3. Above the script tag, add the following style tag to the head element to enable some simple styles for the chat window

        <style>
          #chatBox{width: 100%;height: 80%; position: absolute; top: 0; overflow: scroll;}
          #messageForm{width: 100%; height: 20%; position: absolute; bottom: 0;}
          html body{width: 100%; height: 100%}
        </style>
  4. Add the following HTML5 elements to the body of the page to add the login and chat layout:

        <div id="welcome">
          <h1>WebSocket Chat</h1>
          What is your name? 
          <input type="text" id="name">
          <input type="button" value="Join Chat" onclick="connectToChat();">
        </div>
        <div id="chat">
          <div id="chatBox">
    
          </div>
          <div id="messageForm">
            <input type="text" id="message">
            <input type="button" value="send" onclick="sendMessage();">
          </div>
        </div>
  5. In the following steps, you add JavaScript code to the script tag in the head of the page to add WebSocket communication and user interaction.

  6. Add a url variable with the WebSocket server location. Remember that WebSocket uses the ws protocol.

    var url = "ws://localhost:8087/";
  7. Add empty variables named user and socket:

    var user;
    var socket;
  8. Add a function connectToChat() you'll add socket connection and message handling logic here:

    function connectToChat() {
    }
  9. Inside the connectToChat function, connect to the WebSocket:

    socket = new WebSocket(url);
  10. Inside the connectToChat function, set the user variable to the value of the 'name' element:

    user = document.getElementById("name").value;
  11. Inside the connectToChat function, add the socket onmessage function to receive messages and add content to the innerHTML of the 'chatBox' element:

    socket.onmessage = function (msg) {
      var chatBox = document.getElementById("chatBox");
      var message = JSON.parse(msg.data);
      chatBox.innerHTML = "<b>" + message.user + "</b>:" + message.text + "<br>" + chatBox.innerHTML;
    };
  12. Inside the connectToChat function, add the socket onopen function and send a "<b>Joined the chat</b>"; message:

    socket.onopen = function () {
      var message = {};
      message.user = user;
      message.text = "<b>Joined the chat</b>";
      socket.send(JSON.stringify(message));
    };
  13. Inside the connectToChat function, display the 'chat' element by setting its style attribute to an empty string and hide the 'welcome' element by setting its style attribute to 'display:none'

    document.getElementById("chat").setAttribute("style", "");
    document.getElementById("welcome").setAttribute("style", "display:none");

    This completes the connectToChat function.

  14. Add a sendMessage function.

    function sendMessage() {
      var message = {};
      message.user = user;
      message.text = document.getElementById("message").value;
      socket.send(JSON.stringify(message));
      document.getElementById("message").value = "";
    }
  15. Add a window.onload event handler and hide the 'chat' element by setting its style property to display:none.

    window.onload = function () {
      document.getElementById("chat").setAttribute("style", "display:none");
    }

The completed index.html file:

<!DOCTYPE html>
<html>
  <head>
    <title>Chat Client</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
      #chatBox{width: 100%;height: 80%; position: absolute; top: 0; overflow: scroll;}
      #messageForm{width: 100%; height: 20%; position: absolute; bottom: 0;}
      html body{width: 100%; height: 100%}
    </style>
    <script>
      var url = "ws://localhost:8087/";
      var user;
      var socket;
      function connectToChat() {
        socket = new WebSocket(url);
        user = document.getElementById("name").value;
        socket.onmessage = function (msg) {
          var chatBox = document.getElementById("chatBox");
          var message = JSON.parse(msg.data);
          chatBox.innerHTML = "<b>" + message.user + "</b>:" + message.text + "<br>" + chatBox.innerHTML;
        };
        socket.onopen = function () {
          var message = {};
          message.user = user;
          message.text = "<b>Joined the chat</b>";
          socket.send(JSON.stringify(message));
        };
        document.getElementById("chat").setAttribute("style", "");
        document.getElementById("welcome").setAttribute("style", "display:none");
      }
      function sendMessage() {
        var message = {};
        message.user = user;
        message.text = document.getElementById("message").value;
        socket.send(JSON.stringify(message));
        document.getElementById("message").value = "";
      }
      window.onload = function () {
        document.getElementById("chat").setAttribute("style", "display:none");
      }
    </script>
  </head>
  <body>
    <div id="welcome">
      <h1>WebSocket Chat</h1>
      What is your name? 
      <input type="text" id="name">
      <input type="button" value="Join Chat" onclick="connectToChat();">
    </div>
    <div id="chat">
      <div id="chatBox">

      </div>
      <div id="messageForm">
        <input type="text" id="message">
        <input type="button" value="send" onclick="sendMessage();">
      </div>
    </div>
  </body>
</html>

Testing the WebSocket Chat

To test your chat application locally, you run the Node.js server and then open the index.html page in a browser.

  1. Open a new console window and go to the folder where you saved the server.js file.

  2. Start the Node.js server.

    node server.js

    The server start running. Keep the console window open.

    Console Window running the node server.js
    Description of this image
  3. In a web browser, open the index.html file.

    Web browser with the login page
    Description of this image
  4. Enter a name and click Join Chat. Enter a message in the text field and click send.

    Web browser chat window
    Description of this image
  5. In another web browser window, open the index.html file.

    Two web browsers
    Description of this image
  6. Enter a different name and click Join Chat. Enter a message in the text field and click send. The message appears in both windows

    Web browser chat
    Description of this image
  7. To stop the server, go to the console window where server.js is running and press Ctrl+C.

    Console window stopped
    Description of this image

Preparing the Server Application for Cloud Deployment

For your server application to run properly in the cloud, it must comply with the following requirements:

  • The application must be bundled in a .zip file that includes all dependencies
    Note: Database drivers for Oracle Database Cloud must not be bundled.
  • The .zip file must contain a manifest.json file that specifies what command Oracle Application Container Cloud should run.
  • Your application must listen to requests on a port provided by the PORT environment variable. Oracle Application Container Cloud uses this port to redirect requests made to your application.
  1. Open the server.js file in a text editor.

  2. Locate the PORT variable declaration and change it to a JavaScript conditional statement so that if the process.env.PORT variable is set then that value is used; otherwise, a default port is used.

    var PORT = process.env.PORT || 8087;

    With this declaration, your application listens to the port that Oracle Application Container Cloud provides. Note that this port isn't necessarily the port where service will be located; the final address of your service is provided by the Oracle Application Container Cloud administration console.

  3. Create a new manifest.json file.

  4. Open the manifest.json file in a text editor and add the following content:

    {
      "runtime":{
        "majorVersion":"4"
      },
      "command": "node server.js",
      "release": {},
      "notes": ""
    }

    The manifest.json file contains the target platform and the command to be run.

  5. Compress the server.js, manifest.json, and package.json files and the node_modules folder in a .zip file.

You'll use this .zip file to deploy this application to Oracle Application Container Cloud.

Deploying the Application to Oracle Application Container Cloud

To deploy the application to Oracle Application Container Cloud, you use the .zip file that you created in the previous section. Use the administration console to upload and deploy the application.

  1. Open the Oracle Application Container Cloud Service console.

  2. Click Create Application and then Node.

  3. In the Application section, enter ChatService for the name of your application, click Browse.

  4. On the File Upload page, select the zip file, and click Open.

  5. Type any details for the application and click Create.

  6. Copy the URL of your deployed application from the Oracle Application Container Cloud home page. you'll use it in the next section.

    Oracle Application Container Cloud Home
    Description of this image

Connecting to the Deployed Service with the HTML5 and JavaScript Client

Now that the application is running on the Cloud, modify the client application to connect to the cloud server.

  1. Open the index.html file, open it in a text editor.

  2. Locate the line where you define the server URL: var url = "ws://localhost:8087/";

  3. Replace "ws://localhost:8087/" with the URL you copied in the previous section. Change the protocol from http to ws or from https to wss.

    Browser windows and text editor displaying URL to be replaced
    Description of this image
  4. Open the index.html file in a web browser and test the application.

Your client HTML5 application is now connected to the Node.js service that you deployed in the Oracle Application Container Cloud.

Want to Learn More?