0% found this document useful (0 votes)
19 views

Using websockets in APEX for automatic refresh with nodejs _ emoracle1

The document discusses implementing a websocket server using Node.js for automatic page refresh in Oracle APEX applications. It provides a step-by-step guide on setting up the server, installing necessary modules, and creating a procedure to push messages to clients. Additionally, it includes code snippets and troubleshooting tips for common issues encountered during implementation.

Uploaded by

sharp wahbani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views

Using websockets in APEX for automatic refresh with nodejs _ emoracle1

The document discusses implementing a websocket server using Node.js for automatic page refresh in Oracle APEX applications. It provides a step-by-step guide on setting up the server, installing necessary modules, and creating a procedure to push messages to clients. Additionally, it includes code snippets and troubleshooting tips for common issues encountered during implementation.

Uploaded by

sharp wahbani
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

emoracle

THINGS ON MY MIND, MOSTLY ORACLE

Apr
11 Using websockets in APEX for automatic refresh 12
with nodejs
In my former post Using websockets in APEX for automatic refresh I
explained how to implement a mechanism with an external
websocketserver to push a refresh to an APEX page. It used Beaconpush.

But I didn’t like the dependency on an external websocketserver (I’m just


that way), so I investigated what it should take to implement my own
websocketserver.
Introducing node.js

Node.js is a platform built on Chrome’s JavaScript runtime for easily


building fast, scalable network applications. Node.js uses an event-driven,
non-blocking I/O model that makes it lightweight and efficient, perfect for
data-intensive real-time applications that run across distributed devices.

JavaScript is a growing skill amongst Oracle/APEX developers, so it was a


logical choice to look into using server-side JavaScript to implement a
http/websocketserver combination. The idea was to create a very simple
server which the clients could connect to using the websocket-mechanism.
The database should be able post requests to the HTTP-part of the server
that would be used to the connected clients.

Install node.js

On the website of node.js you can download an installer for node.js. I


downloaded the msi (I’m on a Windows 7 machine).

Install websocket.
Node.js works with modules that can be installed. For this example we need
the websocket module. To install, use the NPM executable

npm install websocket


As a sidenote, this installation failed on my machine. I think the node.js
version was not compatible with the websocket version (1.0.4). I had to
install one version lower:

npm install [email protected]

Create the server.js

As I mentioned before, we are talking here about server-side JavaScript. So


you have to create a JavaScript file, e.g. server.js

"use strict";

process.title = 'database-chat';

var config = {
port:1337
};

/*
We need a HTTP-server and a websocketserver
*/
var webSocketServer = require('websocket').server;
var http = require('http');

/*
We need to keep record of connected clients
*/
var clients = [ ];

/*
The HTTP server
*/
var server = http.createServer( function(req, resp){
var body = '';
var json;
req.setEncoding('utf8');
resp.writeHead(200,{'Content-Type':'application/json' });

req.on('data', function(data) {
body += data.toString();
/*
When we get a stringified JSON-object, that's oke.
If not, we just create one with one attribute
*/
try {
json = body;
var test = JSON.parse(json);
}
catch (e) {
json = JSON.stringify({ 'message':body} );
}
/*
Push the JSON-string to all the connected clients
*/
for (var i=0; i < clients.length; i++) {
clients[i].sendUTF(json);
}
resp.end(JSON.stringify({ message: 'Send to '+ clients.le
});
});

/* Start listening on the configured port an write to standar


server.listen(config.port, function() {
console.log((new Date()) + " Server is listening on port
});

/*
WebSocket server
*/
var wsServer = new webSocketServer({
// De WebSocket server is tied to a HTTP server.
httpServer: server
});

/* If a client connects to the websocketserver,


this callback accepts the request and adds it to the list
*/
wsServer.on('request', function(request) {
console.log((new Date()) + ' Websocketconnection from ori
var connection = request.accept(null, request.origin);
// we need to know client index to remove them on 'close'
var index = clients.push(connection) - 1;
console.log((new Date()) + ' Connection accepted.');

connection.on('close', function(connection) {
console.log((new Date()) + " Peer " + connection.
clients.splice(index, 1);
});

});

Start the server

Starting this server.js script is easy. In a command window type


node server.js

You will get something like

But what is a server without the client?

First of all you will have to have some sort of procedure on the database
that will sent a message to your server.js

procedure push
( p_text in varchar2
)
is
l_clob clob;
begin
l_clob := APEX_WEB_SERVICE.MAKE_REST_REQUEST
( p_url => 'http://127.0.0.1:1337'
, p_method => 'POST'
, p_body => '{"message":"'||p_text||'"}'
);
end;

With such a procedure you can e.g. push the message REFRESH to you
page and refresh the region.
Create a page with an interactive report that you want to be refreshed.
In the page footer add the following script:

$(function(){
window.WebSocket = window.WebSocket || window.MozWebSocket;

if (!window.WebSocket) {
console.log('Sorry, no websockets');
}
else {
var connection = new WebSocket('ws://127.0.0.1:1337');

connection.onerror = function (error) {


console.log( 'Sorry, but there is some problem with you
};

connection.onmessage = function (message) {


console.log(message.data);
try {
var json = JSON.parse(message.data);

if (json.message=='REFRESH') {
gReport.pull();
}
else {
console.log(json.message);
}

}
catch (e) {
console.log('This is not valid JSON: ' + message.data
}
};
}
});

and that’s it.

Mind you, this is just one implementation, but you can push every database
event to the clients page.

Posted in APEX, Non-Oracle

12 THOUGHTS ON “USING WEBSOCKETS IN APEX FOR AUTOMATIC REFRESH


WITH NODEJS”

 
Joe Upshaw
— 14 FEBRUARY 2013 AT 15:12

One small item that I noted…not sure of your APEX version but, under
4.2.1.00.08, the name of the method argumnet to
APEX_WEB_SERVICE.MAKE_REST_REQUEST is p_http_method rather than
p_method.

Reply

dopple
— 18 DECEMBER 2013 AT 14:58

Thanks Joe. This sorted my issue. I am using apex 4.1 with the
restful web services patch.

Reply

Joe Upshaw
— 14 FEBRUARY 2013 AT 18:54

Great article! This was exactly what we needed and, given the nature of our
business, we wouldn’t have been able to employ connections to a third
party. Thanks for sharing.

Reply

Brian
— 18 FEBRUARY 2014 AT 16:08

This is great!!! Thank you for posting this. Exactly what I needed and it
works perfectly.

Reply

Brian
— 19 FEBRUARY 2014 AT 17:32

One thing, in a multiuser environment, I am unsure if the clients


array is slicing off the correct connection on disconnect…I might be
wrong…not sure…. .

Just to make sure, I added an global var clientId at the top of


script, and then inside of the on request:

clientId = clientId +1;


var id = clientId;
clients.push({id:id, connection:connection});

and then in the onclose:


for (var i=0; i<clients.length;i++){
if (clients[i].id == id){
clients.splice( i, 1);
break;
}
Reply

Brian
— 19 FEBRUARY 2014 AT 17:53

Here’s another way to do manage the clients index: without


needing to add an id (like I did above):

connection.on(‘close’, function(closeReason, description) {


var index = clients.indexOf(connection);
if (index !== -1) {
clients.splice(index, 1);
}
});

I have not tried this code (because I need my own id for other
reasons). I got this from looking at the sample code of
websockets: https://github.com/Worlize/WebSocket-
Node/blob/master/test/libwebsockets-test-server.js

Brian
— 20 FEBRUARY 2014 AT 05:14

Just wanted to update… it does look like there is a problem in the onclose
function.

Also doing what is in the example code does not work: var index =
clients.indexOf(connection); so test this carefully you go this route. This
appears to never find the index.

This is what is working for me:

var clients = {}; // at top of script — create an object not an array!!!!

in the on request do:


clientId = clientId +1;
var id = clientId;
clients[id] = connection;

In onClose do:
delete sockets[id];
Then instead of using for loops use:

var keys = Object.keys(clients);


var len = keys.length;
var i=0;
while (i < len) {
console.log( i + ' — ' + keys[i] );
clients[ keys[i] ].send('xyz');
i++;
}
Reply

Mario
— 30 AUGUST 2017 AT 17:35

Hi,
I got this error when I call the “PUSH” function:

ORA-29273: HTTP request failed


ORA-06512: at “SYS.UTL_HTTP”, line 1130
ORA-12541: TNS:no listener

Can you help me please ?

Reply

magazinecrm
— 24 JANUARY 2018 AT 20:40

Dear Edwin,
when i run server.js i encounter the following error
C:\emoracle>node servera.js
C:\emoracle\servera.js:29
req.on(‘dataunction(data) {
^^^^^^^^^^^^^^^^^^^^

SyntaxError: Invalid or unexpected token


at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:607:28)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Function.Module.runMain (module.js:684:10)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3

kindly guide..
Reply

Edwin van Meerendonk


— 24 JANUARY 2018 AT 21:06

Dit you look at the errormessage. Your javascript is incorrect. It is


req.on(‘data’, function(data)

Reply

magazinecrm
— 25 JANUARY 2018 AT 05:06

Hi Edwin, Thanks for quick reply. Just saved my day..I had


copied the above script via notepad plus editior Seems the
code got changed and then i changed to sublime text 3
And it directly shows where the syntax error is..
i just got the server up..Thanks and cheers

Steve
— 28 JULY 2021 AT 00:23

How does client communicate with the database? For example, if I wanted
to store a list of connected clients in the database so that messages can
then be sent to specific clients?

Reply

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is
processed.
← Disable Oracle 11g ACL
Oracle Native web services
and SOAPUI →

Edwin van Meerendonk, Oracle Certified Developer and -Java Developer, also an
Oracle Certified DBA

Now working since 1995 with several different Oracle products.

Lately, heavily interested and working with Node.js, Angular, React, OracleJet, just
because it's fun.

Edwin lives with his wife and his son in Prinsenbeek, The Netherlands.

RECENT POSTS

Enable IPv6 on an existing -free- compute in OCI


Oracle Forms 6i with Oracle Cloud Infrastructure
Changing the status of an Oracle Apex application with pl/sql
Using a serviceworker with Oracle APEX
Component view in Apex 5.1
Search Search

CATEGORIES

General (16)
Javascript (4)
Non-Oracle (6)
Oracle (28)
APEX (16)
DBA (9)
PL/SQL and SQL (9)
QMS/Headstart (1)
Uncategorized (1)

ARCHIVES

September 2021
September 2019
March 2017
December 2016
July 2016
June 2016
March 2016
July 2015
May 2015
March 2015
November 2014
September 2014
March 2014
February 2014
October 2013
September 2013
August 2013
April 2013
February 2013
November 2012
September 2012
August 2012
June 2012
May 2012
April 2012
March 2012
February 2012

INFO
Create account
Log in
Entries feed
Comments feed
WordPress.com

Create a free website or blog at WordPress.com.

You might also like