A week before or two I published on apex.oracle.com simple apex chat demo. It is demo about how to integrate oracle apex and socket.io (node.js).
Basics, part I: Oracle apex
Oracle apex is a rapid web application development tool for the Oracle database. Using only a web browser and limited programming experience, you can develop and deploy professional applications that are both fast and secure.
Basics, part II: Socket.io
Socket.io is a JavaScript library (uses websockets, more info on wiki) for realtime web applications. It enables realtime, bi-directional communication between web clients and servers. It has two parts: a client-side library that runs in the browser, and a server-side library for Node.js. Both components have a nearly identical API. Like Node.js, it is event-driven.
Proof of concept
Concept was to developed apex region plugin that uses socket.io javascript library for realtime interaction with node.js. Socket.io is composed of two parts, one is included on client side and the other is installed on server side. They communicate through websocket which uses 101 switching protocols to send and receive data. So when message is send to server side, server side propagate the same message to all active socket.io sessions. Also you can see from the concept, that messages are not stored in database.
Client side
On client side apex chat is designed as apex region plugin. Witch uses these js libraries:
- handlebars.js -> compiles html forms with data
- socket.io client side -> client side lib. for realtime communication between web clients and servers.
- jquery witch is included in apex
Beside controling the html form, it also listen for propagated events from websocket and triggers the same in order to send data.
Server side, node.js
Server side is developed in node.js with multiple packages. Underneath there is a list of used packages and short description with links. Comunication with client is through websocket.
- Express.js & http - used to create http server
- socket.io - server side library for websockets
- winston - logger
- mkdirp - 'mkdir -p', creates log folder
- ip - IP address utilities
...
const express = require('express');
const http = require('http');
const socketio = require('socket.io');
const winston = require('winston');
const mkdirp = require('mkdirp');
const ip = require("ip");
...
Socket events
Socket.io is event-driven library, that means communication goes by triggering events and there registration. On server side triggering is done in emit function. If on socket object is not set room property chat then broadcast event to all open socket sessions.
...
var emit = function(emitCmd, data){
...
if (socket.room !== undefined){
socket.in(socket.room).broadcast.emit(emitCmd, data);
} else {
socket.broadcast.emit(emitCmd, data);
}
}
...
emit("new.message", {
username: socket.username,
message : data
});
...
and this is how event is registered on server side:
...
socket.on("add.user", function (data) {
...
socket.username = data.username;
emit("user.joined", {
username: socket.username
});
});
...
So when on client side is triggered event "add.user" (in demo when user set there own username), on server side socket.io catch that event and triggers to all others socket.io session "user.joined" event.
on client side this is much simpler, triggering example:
...
this.socket.emit("new.message", msg);
...
and there registration:
...
this.socket.on("user.joined", function(data) {
...
}.bind(this));
...
List of events that are triggered on client side, note that this events are registered on server side:
- public - send flag that this chat is public is available to everyone
- set.room - send flag that this chat is private
- typing - send flag that user has started to type in message area
- stop.typing - send stop typing flag
- new.message - send new message to server side for propagation to other sessions
List of events that are registered on client side, there are triggered on server side:
- user.joined - received data from server that user has joined in your chatroom, create notification in chat region
- typing - received data from server that user has started typing, create typing info in chat region
- stop.typing - received data from server that user has stopped typing, remove typing info in chat region
- new.message - received new message from server, display message in chat region
- user.left - received data from server that user has left your chatroom (socket.io session is terminated), create notification in chat region
Monitoring network between client and server
Now for this, I used google developer tools for screenshot. In your developer tools under network tab, and WS you can see all traffic (under Frame tab you can see text message that are sended/received) that is currently comming and going.
Deploying on apex.oracle.com / OpenShift Online
Since websocket can do cross-domain (but you will need to have a handshake in order to get this going), I installed plugin on apex.oracle.com and node.js module (server side socket.io) is installed on OpenShift Online. OpenShift Online is Red Hat's public cloud application development and hosting platform that automates the provisioning, management and scaling of applications so that you can focus on writing the code for your business, startup, or big idea. OpenShift Online supports a variety of technologies through use of cartridges, including Java, PHP, Node.js, Python, Perl, MySQL, PostgreSQL, MongoDB, Jenkins, Cron, and more.
The future of apex chat demo
Right now all code/project is available at github.
Note that it is still work in progress. The passed few weeks I received a huge, huge feedback which I am very thankful for.
I also encourage you to submit ideas to github issue page and tag them with label New feature.
Top comments (5)
Great plugin. Thank you
Very nice tutorial and idea.
Tnx Ferzad :)
Hi Ivan,
nice post! Have you gotten this to work with https?
Hi christopher,
I'm afraid not, didn't manage the time... you can subscripe to this issue, once it's done you will get notified.
There is a workaround to hide node.js with apache/nginx.
Best regards
isabolic